使用Rabbitmq轻松设置Rebus。 从消费者窗口服务的命令处理程序中,我正在发布一个事件(在命令处理程序的最开始,然后进行实际处理)。 事件的事件处理程序也位于“使用者”窗口服务中。我注意到,尽管该事件是在一开始就发布的,但是它的事件处理程序仅在命令成功处理后才会执行。
从某种意义上说,除非命令(父级)成功,否则不应处理事件(子级)。
但是,考虑将命令视为工作流,我需要定期发布事件(关于特定状态的完成)。在Rebus中为达到相同目的建议的模式是什么?
答案 0 :(得分:1)
正如您已正确观察到的那样,Rebus会收集从消息处理程序中发送的出站消息,以确保在您的处理程序完成执行后将其发送出去。
原因是,这几乎总是您想要的-因为否则事件可以被发布,并因此可以由其他服务处理,即使您自己的工作单元尚未正确落实(*)。
但是,如果您确实愿意,可以通过暂时删除当前的事务上下文来“逃避” Rebus的外发消息集合:
var transactionContext = AmbientTransactionContext.Current;
AmbientTransactionContext.Current = null;
try
{
// current transaction will never know....
await bus.Publish(whee);
}
finally
{
AmbientTransactionContext.Current = transactionContext;
}
如果您决定使用这种转义事务上下文的方法,建议您将其包装在实现IDisposable
的东西中,这样您的代码应如下所示:
using(new RebusTransactionContextDismantler())
{
// current transaction will never know....
await bus.Publish(whee);
}
(*)您可以想象一种情况,其中某个事件假定FinalPaymentReceived
,但是当订阅者对其进行处理时,该顺序尚未在数据库中进行相应更新,因为尚未完全提交SQL事务。
您还可以想象由于唯一的键约束冲突而无法提交SQL事务,这可能是由于对某些特定对象进行并行工作导致的,在这种情况下,SQL事务将回滚。如果事件在该时间点已经发布(并且可能已处理!),那将是灾难性的。