Отправка электронной почты или SMS с использованием CQRS и доменного дизайна

На данный момент мы создаем новую архитектуру, основанную на принципах CQRS и доменного проектирования. Сейчас у нас есть некоторые дискуссии о том, как мы должны иметь дело с внешним общением. Чтобы конкретизировать вопрос, я использую пример отправки SMS-уведомления, когда клиент создает заказ.

Клиент создает NewOrderCommand, который обрабатывается соответствующим обработчиком команд. Обработчик создает новый объект Order в доменной модели, который генерирует NewcustomerCreatedEvent. Объект сохраняется в хранилище событий, а событие публикуется для всех слушателей.

Пока все хорошо, но теперь вопрос. Куда нам отправлять смс-уведомление?

Наш первый инстинкт сказал нам, что мы должны отправить его, используя прослушиватель событий, который прослушивает NewCustomerCreatedEvent и отправляет сообщение. Проблема этого подхода заключается в том, что отправка SMS также является частью нашей бизнес-логики. Мы продаем размещенные сервисы, чтобы наши клиенты могли видеть все SMS-сообщения, отправленные от их имени. Поскольку отправка сообщения происходит за пределами домена, мы не можем этого сделать.

Итак, мы создали домен SMS, и теперь, когда прослушиватель событий получает NewCustomerCreatedEvent, обработчик событий создает новую команду SendSmsMessageCommand, которая создаст новый объект SMSMessage в нашем домене, отправляет SMS-уведомление и создает событие SmsSent, которое мы используем для создания Посмотреть.

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

Мы думали об отправке SMS на событие SmSSent, но это было бы немного странно, потому что событие говорит, что сообщение уже отправлено, но это не так.

Приведенный выше пример подводит нас к вопросу о том, как работать с внешней связью в концепции CQRS и доменного управления? Мы говорим не только об отправке SMS-уведомлений, но и об отправке счетов и внешней биллинговой системы, а также всех других видов связи с внешним миром. Должны ли мы делать это в области, потому что это бизнес-логика, или мы всегда должны делать это на основе событий в наших обработчиках событий? И если мы сделаем это, допустимо ли использовать события, которые говорят, что сообщение отправлено, когда оно еще не сделано?

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

2 ответа

Решение

Я бы подумал, что предметный объект для смс сообщения не нужен. Вам просто нужно сообщить об отправленных SMS клиенту, правильно? SMS-сообщения не используются ни в одной доменной логике, верно?

Поэтому я бы попросил обработчика отправить SMS, а затем опубликовать другое событие, в котором говорится, что SMS было отправлено, и обработчик события прослушал сообщение, отправленное SMS, и материализовать эту информацию в модели чтения, чтобы клиент мог их просмотреть.

Вы можете использовать Saga или Process Manager, как называет это Microsoft. Это в основном слушает события, которые изменяют состояние саги, и выдает команды, основанные на логике состояния, реализованной в саге.

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

Здесь вы можете найти статью Microsoft о шаблоне saga / process manager:

https://msdn.microsoft.com/en-us/library/jj591569.aspx

И две статьи, содержащие реализации:

http://danielwhittaker.me/2015/03/31/how-to-send-emails-the-right-way-in-a-cqrs-system/

http://blog.jonathanoliver.com/cqrs-sagas-with-event-sourcing-part-ii-of-ii/

Другие вопросы по тегам