首先,让我声明我是命令查询职责分离和事件溯源(消息驱动架构)的新手,但我已经看到了一些重要的设计优势。但是,仍然有一些问题我不清楚。
假设我有一个 Customer
包含名为 postalAddress
的属性的类(聚合根) (Address
类的一个实例,它是一个值对象)。我也有一个 Order
包含(在 OrderItem
对象和其他事物中)一个名为 deliveryAddress
的属性的类(另一个聚合根) (也是 Address
类的一个实例)和一个名为 status
的字符串属性.
客户通过发出 PlaceOrder
下订单命令,触发 OrderReceived
事件。此时订单状态为"RECEIVED"
.订单发货时,仓库有人发出ShipOrder
命令,触发 OrderShipped
事件。此时订单状态为"SHIPPED"
.
业务规则之一是,如果 Customer
更新他们的 postalAddress
在订单发货之前(即状态仍然是 "RECEIVED"
), deliveryAddress
的Order
对象也应该更新。如果状态为Order
已经"SHIPPED"
, deliveryAddress
不会更新。
问题 1. 将这种“有条件的级联地址更新”放在 Saga(又名流程管理器)中的最佳位置是什么? 我假设是这样,因为它正在将一个事件(“客户刚刚更新了他们的邮政地址......”)转换为一个命令(“......所以更新订单 123 的送货地址”)。
问题 2. 如果 Saga 是该工作的正确工具,鉴于只能通过其唯一 ID(在我的情况下为 UUID)检索聚合,它如何识别属于用户的订单?
继续,假设每个聚合代表一个事务边界,如果系统崩溃 后 Customer
的 postalAddress
已更新(CustomerAddressUpdated
事件被持久化到事件存储)但 之前 OrderDeliveryAddressUpdated
可以更新(即,在两个事务之间),然后系统处于不一致的状态。
问题 3. 如何检测并纠正此类“违反”一致性规则的行为?
最佳答案
在大多数情况下,订单的交货地址应该独立于任何其他数据更改,因为客户可能希望将订单发送到任意地址。话虽如此,我将就如何解决这个问题给出我的 2c:
Is the best place to handle this in a process manager?
是的。你应该有一个
OrderProcess
.How would one get hold of the correct
OrderProcess
instance given that it can only be retrieve by aggregate id?
没有什么可以阻止添加任何将数据关联到聚合 ID 的额外查找机制。在我的实验性的、即将上线的机制中,称为 shuttle-recall我有一个
IKeyStore
将任意键关联到 AR Id 的机制。因此,您将能够关联类似 [order-process]:customerId=CID-123;
的内容。作为某些聚合的关键。How are such "violations" of consistency rules detected and rectified?
在大多数情况下,如果可能,它们可以在带外处理。我是否应该从亚马逊订购东西,并在订单发货后尝试更改我的地址,订单仍将发送到原始地址。如果您将客户邮政地址链接到事件订单地址,您可以通知客户 n 个订单的地址已更新,但最近的订单(在一定范围内)没有更新。
至于在处理之前系统停机,您应该有一些有保证的交付机制来处理这个问题。我不会像对待消息传递基础结构(例如服务总线)中的系统事件那样对待这些领域事件。
只是一些想法:)
关于domain-driven-design - 在事件溯源中如何处理一致性违规?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34257897/