如何在事件采购中处理一致性违规?

时间:2015-12-14 00:00:16

标签: domain-driven-design cqrs event-sourcing referential-integrity aggregateroot

首先,让我说明我是Command Query Responsibility Segregation和Event Sourcing(消息驱动架构)的新手,但我已经看到了一些重要的设计优势。但是,我还有一些问题尚不清楚。

假设我有一个Customer类(聚合根),它包含一个名为postalAddress的属性(Address类的实例,它是一个值对象)。我还有一个Order类(另一个聚合根),它包含(在OrderItem个对象和其他东西中)一个名为deliveryAddress的属性(也是Address类的一个实例)和一个名为status的字符串属性。

客户通过发出PlaceOrder命令来下订单,该命令会触发OrderReceived事件。此时,订单的状态为"RECEIVED"。订单发货时,仓库中的某个人发出ShipOrder命令,该命令会触发OrderShipped事件。此时,订单的状态为"SHIPPED"

其中一项业务规则是,如果Customer在订单发货前更新了postalAddress(即状态仍为"RECEIVED"时),deliveryAddress还应更新Order对象的更新。如果Order的状态已经"SHIPPED",则deliveryAddress将不会更新。

问题1.最好放置这个"有条件级联地址更新"在佐贺(又名,流程经理)?我假设是这样,因为它正在翻译一个事件("客户刚刚更新了他们的邮政地址...")到一个命令(& #34; ...所以更新订单123")的送货地址。

问题2.如果Saga是适合该工作的工具,那么它如何识别属于该用户的订单,因为聚合只能通过它的唯一ID来检索(在我的情况是UUID)?

继续,假设每个聚合代表一个事务边界,如果系统在后崩溃 Customer postalAddress已更新({ {1}}事件被持久存储到事件存储区)但之前 CustomerAddressUpdated可以更新(即两个事务之间),然后系统处于不一致状态。< / p>

问题3.此类&#34;违规行为&#34;检测并纠正了一致性规则?

1 个答案:

答案 0 :(得分:3)

在大多数情况下,订单的递送地址应独立于任何其他数据更改,因为客户可能希望将订单发送到任意地址。话虽这么说,我会告诉你如何处理这个问题:

  

在流程管理器中处理此问题的最佳位置是什么?

是。你应该有OrderProcess

  

如果只能通过聚合ID检索,如何获得正确的OrderProcess实例?

没有什么可以防止添加任何其他将数据与聚合ID相关联的查找机制。在我的实验性,即将上线的机制shuttle-recall中,我有一个IKeyStore机制,可以将任意密钥与AR Id相关联。因此,您可以将[order-process]:customerId=CID-123;之类的内容与某些聚合关联起来。

  

这种&#34;违规行为&#34;检测并纠正了一致性规则?

在大多数情况下,如果可能的话,他们可以在带外处理。我应该从亚马逊订购一些东西,并且在订单发货后我尝试更改我的地址,订单仍然是原始地址。如果您将客户邮政地址与活动订单地址相关联,则可以通知客户 n 订单数已更新其地址,但最近的订单(在某个容差范围内)没有。< / p>

至于系统在处理之前停机,你应该有一些保证的交付机制来处理这个问题。我不认为这些域事件与我在服务总线等消息传递基础结构中考虑系统事件的方式相同。

只是一些想法:)