在CQRS域驱动设计系统中,常见问题解答说传奇不应该查询读取端({{3}})。但是,一个saga监听事件以执行命令,并且因为它执行命令,它本质上是一个“客户端”,所以为什么saga不能查询读取模型?
答案 0 :(得分:3)
Sagas不应该向读取方(投影)查询它完成任务所需的信息。原因是您无法确定读取方是否是最新的。在最终一致的系统中,您不知道何时更新投影,因此您无法依赖其状态。
这并不意味着传奇不应该持有国家。在许多情况下,Sagas需要跟踪状态,但是传奇应该负责创建该状态。我认为,这可以通过两种方式完成。
它可以通过从事件存储中读取事件来建立其状态。当它收到它应该触发的事件时,它将从存储中读取它需要的所有事件,并以与聚合相似的方式构建其状态。这可以通过创建新流在Event Store中实现。
另一种方式是它持续监听来自事件存储的事件并建立状态并将其存储在某些数据存储上,如投影所做的那样。小心这种方法。您不能像使用投影一样回复传奇。如果您需要更改存储状态的方式并希望重建它,请确保不执行已执行的命令。
答案 1 :(得分:1)
主要是关注问题的分离。流程管理员(sagas)是负责协调活动的状态机。如果进程管理器想要影响更改,它将调度命令(异步)。
另外:什么是阅读模型?这是对已发生的一系列事件的预测。因此,如果处理器关心那些事件......它不应该一直订阅它们吗?所以这里有造型气味。
可能的问题:
流程管理器应该一直在监听流中的早期消息,以便在此消息到达时它处于正确的状态。
当前事件应该更丰富(以便流程管理员需要"已经存在的数据)。
...变体 - 命令处理程序应该正在侦听不同的事件,而且应该更丰富。
您想要的查询应该是对已经知道答案的聚合的命令
并且失败了所有其他
向服务发送命令,该服务运行查询并调度事件作为响应。这听起来很奇怪,但是让流程管理员向调度服务发送消息,以及被唤醒"已经很常见了。当一段固定的时间过去时。
答案 2 :(得分:0)
Sagas使用命令模型来更新系统状态。命令模型包含业务规则,并且能够确保更改在给定域中有效。 为此,命令模型具有所需的所有可用信息。
另一方面,读取模型具有完全不同的目的:它构造数据以便适合于提供信息,例如,在网页上显示。由于saga具有通过命令模型所需的所有信息,因此它不需要读取模型。 更糟糕的是,使用saga中的读取模型会引入额外的耦合并大大增加系统的整体复杂性。
这并不意味着您绝对不能使用读取模型。但如果你这样做,请务必了解后果。对我来说,这个标准非常高,我总是找到一个不同的解决方案。