2013-05-20 7 views
1

Итак, возьмем обычный пример заказа. Предполагая, что у модели с богатым доменом есть вызов Order.place(). Кажется, что в наши дни есть дополнительные задачи, связанные с этим действием: указывает на события домена. Итак, допустим, этот вызов вызывает событие «OrderPlaced». Обычная вещь, которая происходит после размещения события, заключается в том, что мы отправляем электронное письмо с подтверждением, поэтому мы создаем прослушиватель событий для этого события и отправляем электронное письмо.Отключить прослушиватели событий для доменных событий? или как прекратить выполнение в противном случае требуемых сообщений о событиях в конкретных случаях использования

Так просто: Order.place()> OrderPlaced события поднятого> EmailForOrderPlaced слушатель пожары> Электронная почта отправляется

У нас также есть регистрация, которая работает аналогичным образом поднятого (User.register()> UserRegistered события> Регистрация слушателей пожары> Электронная почта отсылается)

Однако:

проблема (а состоят задачи - оленья кожа иметь смысл - однако много реальных потребностей бизнеса не все равно):

Теперь мы хотим предложить функцию регистрации + заказа в одном и против обычного электронного письма на регистрацию + одно электронное письмо для заказа, мы хотим только отправить одно электронное письмо, содержащее оба. Это опасная проблема, поэтому мы обычно создаем службу домена, которая делает это, однако, если мы вызываем User.register(); Order.place(); теперь он будет запускать 2 события, как обычно, рассылает клиенту электронные письма (нормально, но это не так, но это пример)

Итак, как нам обойти это? Очевидно, что отправка комбинированного сообщения электронной почты не является проблемой, потому что мы можем поднять событие для этого в службе, но это все равно оставляет нам оригинальные 2 письма. Если я отключу 2 слушателя в службе до того, как я выполню 2 вызова, это на самом деле означает, что я должен знать об их функциональности, и каждый раз, когда добавляется новый, я должен вернуться к службе, , и т. д., есть ли лучший способ, который бы легко сделал это?

ответ

1

У вас есть несколько вариантов.

Прежде всего, сделайте прецедент явно. Например, вы можете добавить bool в событие UserRegistered, указав, что пользователь был зарегистрирован как часть создания заказа. Это позволит обработчикам электронной почты отправлять соответствующие письма.

Другой вариант - создать обработчик, который отправляет электронные письма для обоих событий. Начиная с emails shouldn't be sent immediately anyway, обработчик, после фиксации, определит, какие события были получены во время данной единицы работы, и таким образом определите тип отправляемой электронной почты. Если оба события прибыли, отправьте одно электронное письмо, в противном случае отправьте электронное письмо, соответствующее полученному событию. Чтобы это работало, вы должны убедиться, что у обработчиков есть срок службы на единицу работы.

Наконец, копайте глубже, обратите внимание, что вам необходимо заполнить агрегаты при игре, User и Order. В идеале, особенно в распределенных сценариях, вы не должны изменять агрегаты в рамках одной транзакции. Чтобы реализовать прецедент, требующий изменения агрегатов, создайте saga, также известный как диспетчер процессов. С помощью саги каждый агрегат изменяется в своей транзакции и как часть транзакции, и сообщение отправляется для перехода к следующему шагу (в этом случае есть 2 шага). Сага получит инициирующее сообщение, которое называется RegisterUserAndCreateOrder. Затем он зарегистрирует пользователя, затем заказ, и по завершении обоих он отправит соответствующее письмо.Обратите внимание, что пользователь и заказ могут быть созданы одновременно. Взгляните на here, чтобы узнать больше об этом событии.