从命令处理程序中发布的事件

时间:2018-09-10 04:20:57

标签: rebus rebus-rabbitmq

使用Rabbitmq轻松设置Rebus。 从消费者窗口服务的命令处理程序中,我正在发布一个事件(在命令处理程序的最开始,然后进行实际处理)。 事件的事件处理程序也位于“使用者”窗口服务中。我注意到,尽管该事件是在一开始就发布的,但是它的事件处理程序仅在命令成功处理后才会执行。

从某种意义上说,除非命令(父级)成功,否则不应处理事件(子级)。

但是,考虑将命令视为工作流,我需要定期发布事件(关于特定状态的完成)。在Rebus中为达到相同目的建议的模式是什么?

1 个答案:

答案 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事务将回滚。如果事件在该时间点已经发布(并且可能已处理!),那将是灾难性的。