首页 > 解决方案 > 如何存储 sagas 的数据?

问题描述

从我读到的聚合必须只包含用于保护其不变量的属性。

我还阅读了 sagas can be aggregates 这对我来说很有意义。

现在,我使用 saga 对注册过程进行了建模:在RegistrationStarted事件中,它发送一个命令,如果电子邮件是免费的ReserveEmail,它将触发EmailReserved或给出。EmailReservationFailed然后,侦听器将发送验证链接或通知帐户已存在的消息。

我想RegistrationStarted在这个监听器中使用来自事件的数据(比如 IP 和用户代理)。我该怎么做?

标签: cqrsevent-sourcingaggregaterootsaga

解决方案


Rinat Abdullin 写了一篇很好的 sagas/流程管理器概述。

通常的答案是 saga 拥有它关心的事件的副本,并使用这些事件中的信息来计算要发送的命令消息。

List[Command] processManager(List[Event] events)

通过 ReserveEmail 命令和结果事件推送他们?

是的,这是通常的方法;我们得到一个列表[RegistrationStarted],我们用它来计算结果[ReserveEmail]。稍后,我们将得到[RegistrationStarted, EmailReserved],我们可以使用它来计算下一组命令(如果有的话)。

听起来很乏味。

数据必须以某种方式在两种功能之间传输。因此,您要么将数据从一条消息复制到另一条消息,要么将关联标识符从一条消息复制到另一条消息,然后允许消费者决定如何使用关联标识符来获取数据的副本。

将这些数据存储在 saga 中?但它们不用于保护不变量。

您通常会将事件存储在 sagas 中(以跟踪发生的事情)。这为您提供了事件中提供的数据的副本。您没有要保护的不变量,因为您只是在缓存其他地方做出的决定的副本。您通常不会让流程管理器运行查询来收集其他数据。

那么最终的一致性呢?

就其性质而言,传奇总是“最终一致”。saga 实例的“状态”只是其他地方控制的数据的缓存副本。到 saga 看到数据时,数据可能是纳秒级的,假装数据是“现在”是没有意义的。

如果我理解正确,我可以将我的传奇建模为一个注册聚合,存储其相关标识符是它自己的标识符的所有事件?

Udi Dahan,撰写有关 CQRS 的文章

这是我可以告诉你的最有力的迹象,表明你正在正确地进行 CQRS:你的聚合根是 sagas。


推荐阅读