Подтвердить что ты не робот

Должны ли возникать события домена в транзакции или за ее пределами?

В нашем приложении мы поднимаем события домена, когда что-то меняется в модели домена. Некоторые из задач, выполняемых обработчиками событий, должны выполняться в рамках той же транзакции, которая использовалась при возникновении события, другие задачи должны выполняться вне этой транзакции.

Например,

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

Как вы подходите к этой проблеме?

  • Поднимите два события, одно внутри транзакции и одно за пределами транзакции.
  • Поднять событие внутри транзакции, но использовать обработчик событий для отправки запроса Async для обновления пользовательского интерфейса?

Вариант 1 кажется путаным, так как имена событий должны каким-то образом передавать их в транзакцию или из нее, но с обработчиками домена 2 события домена всегда должны предполагать, что они вызываются синхронно из транзакции.

Может быть, есть лучший подход?

4b9b3361

Ответ 1

У меня была аналогичная проблема. Модель домена публиковала события (используя технику Udi Dahan описывает здесь). Затем я понял, что мои обработчики, связанные с пользовательским интерфейсом, вызывается, даже если что-то пойдет не так, и транзакция будет откат позже.

Чтобы исправить это, я ввел еще одну роль в систему, другой вид обработчика событий. У меня есть ITransactionalEventHadneler и INonTransactionalEventHandler. Первые были синхронно вызваны в методе DomainEvents.Publish(). Последние были поставлены в очередь для вызова, как только транзакция будет совершена (с использованием перехватчиков System.Transactions). Решение отлично работало и было вполне читаемым и поддерживаемым.

Ответ 2

Я думаю, что оба подхода могут быть хорошими, просто придерживайтесь одного и того же подхода в каждой части вашего кода:

  • вам понадобятся два (или более) обработчика событий, один для контекста модели домена, который внутри области транзакции и другие (-ы) для вспомогательных контекстов, например пользовательский интерфейс. Ваш код домена не должен заботиться о том, что делают другие части кода, просто сообщите им об изменениях в данных домена.
  • метод обработчика событий вашего домена может отправлять асинхронные события в пользовательский интерфейс или другие модули. События домена должны быть синхронными, иначе вам понадобится двухфазная фиксация, чтобы сохранить транзакцию.

Мне лично нравится вариант 2, потому что он сохраняет код домена более чистым и, используя асинхронную связь, ядро ​​и другие модули будут развязаны, поэтому проблемы во внешних модулях не будут препятствовать работе ядра. С другой стороны, могут быть ситуации, когда вариант 1 является более выгодным.