Сага, которые зависят от событий из прошлого

У меня есть вопрос, как бороться с сагой, где принятие решения зависит от события, которое было опубликовано до создания саги.

Вот пример, чтобы проиллюстрировать мою проблему:

Представьте, что у меня есть CustomerAR и OrderAR. Когда customerAR создается, начинается процесс проверки, результатом которого является сумма заказа, которую клиент может потратить без специальной авторизации. Я не буду вдаваться в подробности об этом процессе, потому что он вне контекста. Когда сумма рассчитывается, в CustomerAR отправляется команда с рассчитанной суммой, а CustomerAR публикует событие (CustomerMaxOrderAmountEvent) с этим значением. Все идет нормально.

Затем через несколько недель клиент размещает заказ. OrderAR создан и запускает мою OrderSaga. Сага ждет, пока заказ не будет создан полностью, а затем должна принять решение, если ей нужно отправить AutorizationCommand для этого заказа. Чтобы принять это решение, он должен знать, опубликовано ли CustomerMaxOrderAmountEvent и значение суммы. Обычно OrderSaga также подписывается на CustomerMaxOrderAmountEvent, но проблема в том, что это событие никогда не произойдет, потому что оно уже произошло в прошлом.

Как мне с этим бороться. Если я запрашиваю модель чтения, чтобы узнать значение, должен ли я отправить команду для получения значения, должен ли я сделать ссылку на CustomerAR, должен ли я воспроизвести все исторические события в саге, чтобы он уже знал историю.

ОБНОВИТЬ

Обратите внимание, что речь идет о концепции, а не об этом конкретном примере. Этот пример является чистым для прояснения проблемы: "2 несвязанных агрегатных корня, которые не являются частью одного и того же ограниченного контекста".

Благодарен за помощь.

Melvin

2 ответа

Я бы пошел для более простого решения - просто добавьте эту информацию (например, в виде HasCustomerReachedMaxOrderAmount) к событию, которое начинает сагу.

Второй вариант, который я бы выбрал, - это подготовить модель чтения, предназначенную для использования с Sagas, и оттуда запросить данные, но я собрал бы всю необходимую информацию еще до запуска саги. Это обогащение может быть выполнено обработчиком исходного события, вызванного AR, поскольку это не является частью агрегированного / ограниченного контекста.

Однако в большинстве случаев достаточно опираться на данные, передаваемые с событиями, потому что Sagas должен содержать бизнес-логику только в форме процесса. Это очень часто означает, что у вас может быть более одной саги (следовать вашему примеру OrderSaga а также OrderWithMaxAmountSaga).

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

Я бы смоделировал этот сценарий так: CustomerAR рассчитывает максимальную сумму; клиент размещает заказ -> OrderAR создается с информацией о максимальной сумме для этого клиента, Order проверяет необходимость дополнительной авторизации -> Saga начать. Дело в том, что информация о максимальной сумме важна как для CustomerAR (где это может измениться) и OrderAR (где он неизменен).

Я только начинаю баловаться с DDD, и я не собираюсь повторять то, что сказал kstaurch, но вот некоторые мысли, которые я думал о вашем сценарии:

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

  2. Что если сага всегда посылает команду авторизации, но именно часть авторизации обрабатывает экран максимального заказа? Если вы говорите "Если сумма превышает $X, то получите авторизацию", возможно, ваша бизнес-модель также думает об этом как "Если она ниже $X, автоматически одобрите". Преимущество заключается в том, что все вопросы об утверждении (в том числе о том, следует ли получать одобрение) могут быть перенесены в объект утверждения или в саги.

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