cqrs - 如何存储 sagas 的数据?
问题描述
从我读到的聚合必须只包含用于保护其不变量的属性。
我还阅读了 sagas can be aggregates 这对我来说很有意义。
现在,我使用 saga 对注册过程进行了建模:在RegistrationStarted
事件中,它发送一个命令,如果电子邮件是免费的ReserveEmail
,它将触发EmailReserved
或给出。EmailReservationFailed
然后,侦听器将发送验证链接或通知帐户已存在的消息。
我想RegistrationStarted
在这个监听器中使用来自事件的数据(比如 IP 和用户代理)。我该怎么做?
- 将这些数据存储在 saga 中?但它们不用于保护不变量。
ReserveEmail
通过命令和结果事件推动他们?听起来很乏味。- 将传奇投影到读取模型?那么最终的一致性呢?
- 另一种方式?
解决方案
Rinat Abdullin 写了一篇很好的 sagas/流程管理器概述。
通常的答案是 saga 拥有它关心的事件的副本,并使用这些事件中的信息来计算要发送的命令消息。
List[Command] processManager(List[Event] events)
通过 ReserveEmail 命令和结果事件推送他们?
是的,这是通常的方法;我们得到一个列表[RegistrationStarted]
,我们用它来计算结果[ReserveEmail]
。稍后,我们将得到[RegistrationStarted, EmailReserved]
,我们可以使用它来计算下一组命令(如果有的话)。
听起来很乏味。
数据必须以某种方式在两种功能之间传输。因此,您要么将数据从一条消息复制到另一条消息,要么将关联标识符从一条消息复制到另一条消息,然后允许消费者决定如何使用关联标识符来获取数据的副本。
将这些数据存储在 saga 中?但它们不用于保护不变量。
您通常会将事件存储在 sagas 中(以跟踪发生的事情)。这为您提供了事件中提供的数据的副本。您没有要保护的不变量,因为您只是在缓存其他地方做出的决定的副本。您通常不会让流程管理器运行查询来收集其他数据。
那么最终的一致性呢?
就其性质而言,传奇总是“最终一致”。saga 实例的“状态”只是其他地方控制的数据的缓存副本。到 saga 看到数据时,数据可能是纳秒级的,假装数据是“现在”是没有意义的。
如果我理解正确,我可以将我的传奇建模为一个注册聚合,存储其相关标识符是它自己的标识符的所有事件?
Udi Dahan,撰写有关 CQRS 的文章:
这是我可以告诉你的最有力的迹象,表明你正在正确地进行 CQRS:你的聚合根是 sagas。
推荐阅读
- python - 如何避免在 Django 中重复相同的代码块?
- python - 最接近 R 的 nlminb 的 Python 的 scypy 求解器?
- exe - exe程序中的编译器在哪里?
- c# - 无法运行使用 Visual Studio 17 中的安装项目安装的应用程序
- sonarqube - 在 Travis CI 上使用 Sonarcloud 时出现授权错误
- javascript - 当状态改变时,使用来自 redux 的连接助手的 React Native 不会重新渲染?
- php - 如何在不更改版本的情况下解决 Laravel 中的 PHP 错误?
- javascript - Unity3D/PowerUI 没有注册简单的 CSS 翻译?
- javascript - Mup Deploy 在 AWS 上不起作用
- python - 无法使用 Kafka(超过 1.3 MB)处理大消息?