使用 Rabbitmq 简单设置 Rebus。 在使用者窗口服务的命令处理程序中,我正在发布一个事件(在命令处理程序的最开头,然后我正在执行实际处理(。 事件的事件处理程序也位于使用者窗口服务中。我注意到,尽管事件是在一开始发布的,但它的事件处理程序仅在命令成功处理后才会执行。
在某种程度上,除非命令(父级(成功,否则不应处理事件(子级(是有道理的。
但是,将命令视为工作流,我需要在常规阶段(关于特定状态的完成(发布事件。Rebus 中建议的模式是什么来实现相同的目标?
正如您正确观察到的那样,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 事务将回滚。如果事件在那个时间点已经发布(并且可能已经处理!(,那将是相当灾难性的。