据我所知,聚合必须仅包含用于保护其不变性的属性。
我还读到sagas可以是聚合体,这对我来说很有意义。
现在,我使用一个传奇来对注册过程进行建模:在RegistrationStarted
事件上,它会发送一个ReserveEmail
命令,如果电子邮件免费,它将触发一个EmailReserved
或EmailReservationFailed
或不。然后,侦听器将发送验证链接或一条消息,告知帐户已经存在。
我想在此侦听器中使用来自RegistrationStarted
事件的数据(例如IP和用户代理)。我该怎么办?
ReserveEmail
命令和结果事件推动它们?听起来很乏味。答案 0 :(得分:2)
Rinat Abdullin wrote a good overview of sagas / process managers。
通常的答案是,传奇具有它关心的事件的副本,并使用这些事件中的信息来计算要发送的命令消息。
List[Command] processManager(List[Event] events)
通过ReserveEmail命令和结果事件将其推送?
是的,这是通常的方法;我们得到一个列表[RegistrationStarted]
,然后使用它来计算结果[ReserveEmail]
。稍后,我们将获得[RegistrationStarted, EmailReserved]
,我们可以使用它来计算下一组命令(如果有)。
听起来很乏味。
数据必须以某种方式在两种功能之间传递。因此,您要么将数据从一条消息复制到另一条消息,要么将correlation identifier从一条消息复制到另一条消息,然后让使用者决定如何使用相关标识符来获取数据的副本。 / p>
将这些数据存储在传奇中?但是它们并不用于保护不变式。
您通常将事件存储在sagas中(以跟踪发生的情况)。这样可以为您提供事件中提供的数据的副本。您没有要保护的不变式,因为您只是在缓存其他地方所作的决策的副本。通常,您不会让流程管理器运行查询来收集其他数据。
最终一致性如何?
从本质上讲,萨加斯始终会“最终保持一致”;传奇实例的“状态”只是在其他位置控制的数据的缓存副本。到传奇故事出现时,数据可能已经过了十亿分之一秒的时间,因此没有必要假装数据是“现在”。
如果我理解正确,我可以将我的传奇建模为一个注册聚合,以存储所有相关标识符为其自身标识符的事件?
Udi Dahan,writing about CQRS:
这是最有力的暗示,我可以告诉您您在正确地执行CQRS:您的总根是无花果。