Прежде всего, позвольте мне сказать, что я новичок в разделении ответственности запросов запросов и событийных событий (архитектура Message-Drive), но я уже вижу некоторые существенные преимущества дизайна. Тем не менее, есть еще несколько вопросов, по которым я неясен.Каковы нарушения последовательности в обработчике событий?
Скажем, у меня есть класс Customer
(совокупный корень), который содержит свойство postalAddress
(экземпляр класса Address
, который является объектом значения). У меня также есть класс Order
(другой общий корень), который содержит (среди OrderItem
объектов и т. Д.) Свойство, называемое deliveryAddress
(также экземпляр класса Address
) и строковое свойство, называемое status
.
Клиент отправляет заказ, отправив команду PlaceOrder
, которая вызывает событие OrderReceived
. На данный момент статус заказа "RECEIVED"
. Когда заказ отправляется, кто-то на складе выдает команду ShipOrder
, которая вызывает событие OrderShipped
. На данный момент статус заказа "SHIPPED"
.
Один из бизнес-правил является то, что если Customer
обновляет их postalAddress
до того, как заказ будет отправлен (то есть, в то время как состояние еще "RECEIVED"
), то deliveryAddress
из Order
объекта также должны быть обновлены. Если статус Order
был уже "SHIPPED"
, то deliveryAddress
не обновлялся.
Вопрос 1. Лучшее место для размещения этого «условно-каскадного обновления адреса» в саге (a.k.a., Process Manager)? Я так полагаю, учитывая, что он переводит событие («Клиент только обновил свой почтовый адрес ...») в команду («... так обновите адрес доставки порядка 123»).
Вопрос 2. Если сага является правильным инструментом для задания, как она идентифицирует заказы, принадлежащие пользователю, учитывая, что агрегат может быть получен только по его уникальному идентификатору (в моем случае UUID) ?
Продолжая, учитывая, что каждый агрегат представляет транзакционную границу, если бы система была врезаться послеCustomer
«s postalAddress
было обновлен (CustomerAddressUpdated
события сохраняются в хранилище событий), но перед темOrderDeliveryAddressUpdated
может быть обновлено (т. е. между двумя транзакциями), то система остается в противоречивом состоянии.
Вопрос 3. Как выявляются и исправляются такие «нарушения» правил согласованности?
Цените идеи. Я думал, что объект 'OrderProcessManager' может предоставить кэш/индекс (карту UUID-клиентов для вектора UUID-ордеров заказов для тех заказов, которые не были отправлены, таким образом, являются« stateful ») и когда' OrderProcessManager 'видит событие' OrderShipped', он просто удаляет UUID заказа из своего внутреннего кеша, но ваша идея о произвольных парах ключ/значение, хранящихся в хранилище событий, против совокупности является проницательной. – magnus
'Как получить доступ к правильному экземпляру OrderProcess, учитывая, что его можно получить только с помощью идентификатора aggregate?' Wait ... вы говорите, что объекты Process Manager также хранятся в репозитории (например, хранится «OrderProcess» в «OrderProcessRepository» - с использованием ES, конечно) ??? – magnus
Наличие 'OrderProcessRepository' * - это опция в настраиваемом мире реализации. если вы используете C#, я имею 3 реализации диспетчера процессов в [образцах моей служебной шины] (https://github.com/Shuttle/shuttle-esb-samples) в папке «Shuttle.ProcessManagement». Главное, что есть немного данных, которые вы собираетесь знать **, например, номер клиента. В обработке кода, создающей исходный поток, вы должны иметь доступ к этим данным, а в точке * * * вы должны создать связь между идентификатором AR и произвольным ключом. –