在事件来源中将快照作为域事件

时间:2018-06-29 16:23:57

标签: event-handling domain-driven-design cqrs snapshot event-sourcing

在我的事件源模型中,我有一些相当恒定的聚合,它将累积大量事件。我正在考虑使用快照来优化这些聚合的重新水合。即骨料是仓库。

我的问题是是否应该为快照创建特定事件,例如“ WarehouseStateSnapshotted” 。在我当前的原型中,快照状态保存在一些命令处理程序中存在的重复代码中。我觉得这不是处理它的正确区域。我宁愿将快照的事件调度到我的服务总线,并由事件处理程序处理以保存快照状态。 但是,这可能会违反它们自身事件的域驱动模式。是否为快照创建了其他人创建的事件?

如果这不是正确的方法,我是否应该至少将快照逻辑移出命令处理程序并移至聚合类中?

谢谢!

编辑:标题和-This注释似乎建议使用快照,因为域事件是错误的处理方法。

EDIT2:简化的问题-将回购注入命令处理程序是否合适?

3 个答案:

答案 0 :(得分:1)

让我先攻击简单的一个。快照逻辑不属于聚合。是否以及何时进行快照纯粹是性能问题,因此不属于业务规则。通过想象具有无限资源的服务器,有助于划清界限。如果您不需要在这台出色的机器上执行“事物”,那么“事物”就不属于总体。

在您上面发布的链接中,我同意RBanks54的观点,由于快照列出的所有原因,快照不属于聚合事件流。我认为您的解决方案是在服务总线上调度事件,然后以不同的命令处理该事件,这是正确的方法。在处理新事件的上下文中处理快照意味着除非接收到新事件,否则无法快照。在服务总线上具有不同的消息意味着任何进程都可以在适当的时候请求快照。

答案 1 :(得分:0)

我一直在尝试一些事件源,但我不是专家。我并不特别喜欢表示快照的单独“ ”的想法。由于只存储最后一个快照,因此它不是很多流。在仍处于起步阶段的Shuttle.Recall项目中,我将快照存储为普通的域事件,但将它们专门标记为快照,并分别存储最后一个快照版本以加载快照,然后加载该版本之后的事件被应用。我发现了一些优点,因为您还可以围绕快照添加一些功能。

将快照用作纯粹的技术性能改进时,它可能不会为您的域增加太多价值。如果快照不属于聚合/域,那么如何将快照中的聚合水化呢?

在某些情况下,快照可能是域的很大一部分。当您查看每月银行对帐单时,您将不会发现自开设帐户之日起的每笔交易(事件)。相反,我们拥有该月新交易(事件)的期初余额(快照)。这样,“ MonthEndProcessed”事件很可能就是快照。

我也不会真正地购买这样的参数,即快照中包含错误,您将无法修复它,因为事件流是不可变的。如果您的事件包含错误会怎样?你不能修好吗?理想情况下,这些错误不应将其纳入生产系统,但如果确实如此,则应将其修复。无论如何,对我而言,不变性与系统的典型交互有关。一旦事件发生,我们通常不会更改

在某些情况下,返回并将某些事件更改为较新的版本甚至可能是有益的。应该将这些限制降至最低并在理想情况下避免,但在某些情况下也许是实用的。

但是就像我说的...我还在学习:)

答案 2 :(得分:0)

  

我的问题是我是否应该为快照创建特定事件,例如“ WarehouseStateSnapshotted”之类的东西。

“取决于”。

您应查看快照的参考文献是CQRS Documents,作者是格雷格·杨(Greg Young)。它在2010年相对较旧,但是只是作为快照概念的简单介绍。

异步生成快照并将其存储在事件流之外没有什么问题。

您可以在快照过程中使用任何明智的触发器;您不一定需要在流中发生事件。 “每100个事件快照”或“每10分钟快照”或“管理员单击快照按钮时快照”都是可行的。

某些域对它们具​​有自然的节奏,该域本身可能会提供快照-考虑“关闭会计年度的帐簿”。

对于将与域无关的“制作快照”消息放入事件流,我有些怀疑-我认为让聚合负责快照的节奏是不合适的。它没有损坏,但确实有点像以不同的关注点重载了事件流的语义。