【问题标题】:How to store sagas’ data?如何存储 sagas 的数据?
【发布时间】:2018-11-07 00:46:11
【问题描述】:

根据我的阅读,聚合必须只包含用于保护其不变量的属性。

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

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

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

  • 将这些数据存储在 saga 中?但它们不用于保护不变量。
  • 通过ReserveEmail 命令和结果事件推动他们?听起来很乏味。
  • 将 saga 投影到读取模型?那么最终的一致性呢?
  • 另一种方式?

【问题讨论】:

  • 我将 saga 视为可以发出命令的读取模型。在这种情况下,您究竟看到了哪些一致性问题?
  • 假设EmailReserved 事件是在预测传奇之前发布的;我无法获得RegistrationStarted 数据。
  • 它应该像任何其他读取模型一样工作:创建 saga 时,它应该重播所有感兴趣的事件,直到它进入“当前”状态,然后监听传入事件。当然在重播期间它不应该发送命令,只是更新它的状态
  • 我真的不明白;您可以尝试在答案中阐述您的观点吗?
  • 好的,我会尽量给出完整的答案。但是然后我需要了解您的示例中的聚合根是什么,以及它需要什么来决定保留是成功还是失败?它需要知道其他预订的结果吗?

标签: cqrs event-sourcing aggregateroot saga


【解决方案1】:

Rinat Abdullin wrote a good overview of sagas / process managers.

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

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

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

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

听起来很乏味。

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

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

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

最终的一致性怎么样?

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

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

乌迪·达汉,writing about CQRS

这是我能告诉你的最有力的迹象,表明你正在正确地执行 CQRS:你的总根是 sagas。

【讨论】:

  • 如果我理解正确,我可以将我的 saga 建模为一个 Registration 聚合,存储其相关标识符是它自己的标识符的所有事件?
  • 我想你可以,除非你需要了解所有其他电子邮件预订(以确保用户拥有唯一的电子邮件)——在这种情况下,你可能需要一个真正的传奇
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-09
  • 2012-05-09
  • 2021-03-11
  • 1970-01-01
相关资源
最近更新 更多