我正在研究一个小示例应用程序,以学习CQRS和事件源的概念。我有一个Basket
汇总和一个Product
应该独立工作的汇总。
这是一些伪代码来展示实现
Basket { BasketId; OrderLines; Address; }
// basket events
BasketCreated { BasketId; }
ItemAdded { BasketId; ProductId; Quantity }
AddItemSucceeded { BasketId; ProductId; Quantity }
AddItemRevoked { BasketId; ProductId; Quantity }
ItemRemoved { BasketId; ProductId; Quantity }
CheckedOut { BasketId; Address }
Product { ProductId; Name; Price; }
// product events
ProductReserved { ProductId; Quantity }
ProductReservationFailed { ProductId; Quantity }
ProductReservationCancelled { ProductId; Quantity; }
命令与事件非常相似,使用命令性名称而不使用过去式。
现在,这些独立工作就可以了。我发出一个命令AddItem
,它ItemAdded
在Basket
聚合上创建一个事件,该事件完成了对“篮子”状态的处理。同样,对于产品,命令和事件也可以正常工作。
我现在想将其组合成一个过程,该过程将是这样的(就发生的命令和事件而言):
流程经理将执行以下操作:
on BasketCreated: CreateShoppingProcess
on ItemAdded: ReserveProduct
on ProductReserved: SucceedAddingItem // does nothing, but needs to be there so that the basket knows it can check out
on ProductReservationFailed: RevokeAddItem
on RemoveItem: CancelProductReservation
on Checkout: CreateOrder // create an order and so on...
我找不到明确答案的问题是:
- 我是否需要坚持流程经理?看起来像我,但我不确定
- 如果这样做,则需要为流程管理器保存事件。但是,它正在监听的事件与聚合相关。是否向其中添加进程ID?我是否有仅针对流程经理的单独事件?如何做到这一点并尽可能保持干燥
- 我怎么知道这些
ProductReserved
活动是为了什么?可以在BasketId
上面也可以,还是泄漏信息? - 如何保持事件之间的关系,如何知道
ItemAdded
哪个ProductReserved
事件产生了?我会经过EventId
吗?这似乎很奇怪... - 我应该将其实现
Basket
为流程管理器而不是简单的集合吗?
经过更多研究后,我得出以下结论:“传奇”是一种保留自己的事件并从外部监听事件的东西。基本上,它是一种聚合,也可以对自己的小世界之外发生的事件做出反应。
流程管理器处理来自外部的事件并发出命令。可以从共享相同标识符(如correlationId)的聚合事件中重建事件的历史记录。