CQRS:基于多个聚合事件的更高级别状态

时间:2017-10-01 09:08:10

标签: domain-driven-design cqrs event-sourcing

考虑以下情况:

我们有几个共享共同特征的聚合(例如:它们属于同一个用户) 每个聚合的事件用于实现自己的状态。

如果需要更高级别的状态该怎么办?该状态应代表所有用户聚合的总体状态。 考虑有一个特殊的业务逻辑定义更高级别状态的具体化(例如:如果多于x个聚合处于错误状态,则客户聚合状态需要更高级别的错误状态)

此要求涉及实现多个聚合的事件。此外,较高级别的状态被认为是一个事实,因为它完全由较低级别的事件决定。出于这个原因,似乎佐贺的使用在这里是不合适的。

另一方面,

需要在更高级别状态发生转换时发出事件(例如:当多于x个聚合报告错误时,发出可以驱动更多业务逻辑的事件)。因此,根据其他事件生成事件似乎也不合适。

这里推荐的方法是什么?我可以看到Saga如何能够听取较低级别的聚合事件并将其中的一些事件转换为更高级别实体聚合的命令,这些命令反过来会产生自己的事件但是在走这条路线时我无法摆脱这种感觉event => command =>事件流程是一种仪式,而不是一种真正的设计要求。

感谢您的见解

乔纳森

3 个答案:

答案 0 :(得分:3)

Udi Dahan once wrote

  

这是我能给你的最强烈的指示,你知道你正确地做了CQRS:你的根源是传奇。

在这种情况下:"当在更高级别的状态转换时,需要发出事件"是一个很大的线索,有一个更高水平的聚合"这是观察较低级别的事件并应用您的业务逻辑来确定更高级别的状态是否已更改。

此更高级别的聚合可能具有类似

的界面
void handle(LowerLevelEvent e);

因此,较低级别聚合输出其事件,然后管道将该事件的副本携带到较高级别聚合的输入,而较高级别聚合输出较高级别的事件。

请注意,此处没有任何魔力 - 较高级别的聚合不是使用所有事件来决定更高级别的转换,而是仅使用它当前知道的的那些

整个流程看起来像

  • 较低级别的聚合广播event:{id:123}给所有感兴趣的人
  • 管道工程会观察event:{id:123},并作为回应将handle(event:{id:123}) 命令发送给更高级别的聚合
  • 更高级别的聚合应用自己的业务逻辑,在适当时广播自己的事件
  

没有低级别和高级别。

这是一个重点;上面的低级别和高级别标签实际上只是参考点。就集合而言,只有它本身,以及其他一切 - 没有边界层次。

除此之外,这意味着您可以测试更高级别的"没有较低级别聚合甚至存在的聚合行为 - 您只需发送消息并验证其是否正确反应。

答案 1 :(得分:0)

我认为您应该更多地关注您的业务而不是实施设计。是否有任何需要该信息的业务流程?然后继续实施它。

没有低级别和高级别。同一复杂系统只有不同的观点,我们必须做的不同切片才能理解它。这就像我们只能看到2d,但世界是3d。在某些情况下,您必须在现实中选择最适合您的切片。

在您的情况下,您选择在每个聚合上使用事件来保持状态用于命令验证的强一致性;他们利用自己的事件来了解世界。但是你可以对世界有不同的看法,就像聚合物一样。你可以让一个Saga / Process管理器监听相关事件,并根据一些业务需求生成一些命令,进一步改变系统的状态。没关系,这就是复杂系统的工作原理。您只需要围绕这些过程有明确的界限,并使用有界的上下文和上下文映射来保持它们分离。

总之,请继续围绕您确定的任何业务流程创建Sagas。

答案 2 :(得分:0)

在处理流程时,通常有两种方法。

编排

这依赖于隐式过程,让每个聚合参与一个过程,并且事件通常包含所有必需的信息。对我来说,当部分过程可以分成并行位时,这会中断。任何基于人的互动也不适合这一点。也没有对过程状态的看法。

编排

这是我们明确跟踪流程和流程管理员的地方(我更喜欢这个术语高于" saga")。这个可能是为什么有些人认为所有聚合根都是流程管理者,但同一个聚合根可能会参与不同的流程,这意味着如果我们确实将AR视为流程管理者,那么它必须是了解它属于哪个进程。

我更喜欢业务流程,因为您可以查看流程的当前状态。为此,我倾向于让我的流程经理成为一流的公民,因为他们是一个聚合根,但只关注流程管理。

在有界的上下文世界中,我将使用我的流程管理(更高级别)作为一种集成层,因为流程可能涉及多个(较低级别)有界上下文。

例如,CustomerInteractionJournalEMail可能是许多流程的一部分。

在我的较低级别有界上下文级别我让我的消息处理程序响应命令我发布事件。我通常不会对该级别的事件做出反应。

更高级别进程管理有界上下文中,我对通常启动进程的命令和移动进程的事件做出反应沿。