Событие опубликовано в обработчике команд - PullRequest
0 голосов
/ 10 сентября 2018

Простая настройка Rebus с Rabbitmq. Из обработчика команд в службе Consumer Window я публикую событие (в самом начале обработчика команд, а затем выполняю фактическую обработку). Eventhandler для события также находится в службе окна Consumer. Я заметил, что хотя событие было опубликовано в самом начале, его обработчик событий выполняется только после успешной обработки команды.

В некотором смысле имеет смысл, что если команда (родитель) не выполнена успешно, событие (дочерний элемент) не должно обрабатываться.

Однако, рассматривая команду как рабочий процесс, мне нужно регулярно публиковать события (о завершении определенного состояния). Каков шаблон, предложенный в Rebus для достижения того же самого?

1 Ответ

0 голосов
/ 10 сентября 2018

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

...