Как вы правильно заметили, 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 откатывается.Было бы довольно пагубно, если бы события были уже опубликованы (и, возможно, обработаны!) В тот момент.