快照作为事件溯源中的领域事件

Snapshotting as Domain Event in Event Sourcing

我的事件溯源模型中有一些非常稳定的聚合,它们会累积大量事件。我正在考虑使用快照来优化这些聚合的 re-hydration。 IE。聚集体是仓库。

我的问题是我是否应该为快照生成一个特定的事件,比如 "WarehouseStateSnapshotted"。在我当前的原型中,快照状态保存在一些命令处理程序中存在的重复代码中。我觉得这不是处理它的正确领域。我宁愿将快照事件分派到我的服​​务总线,并让事件处理程序处理保存快照状态。 但是,这可能会违反事件自身的域驱动模式。是否有其他人为快照创建了事件?

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

谢谢!

编辑: 标题和 -- This 评论似乎建议快照作为域事件是错误的方法。

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

我先攻略简单的吧。快照逻辑不属于聚合。是否以及何时拍摄纯粹是性能问题,因此不属于业务规则。想象一个拥有无限资源的服务器有助于划清界线。如果您不需要在这台神奇的机器上做“事情”,那么“事情”不属于聚合。

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

我对事件溯源有所涉猎,但我不是专家。我不太喜欢用单独的“stream”表示快照的想法。它不是一个流,因为它只存储最后一个快照。在我的 Shuttle.Recall 项目中,它仍处于起步阶段,我将快照存储为普通域事件,但它们被特别标记为快照,并且最后一个快照版本单独存储以便加载它,然后加载该版本之后的事件被应用。我发现这样做有一些优势,因为您还可以围绕快照添加一些功能。

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

在某些情况下,快照可能是域的重要组成部分。当您查看每月的银行对帐单时,您不会找到从开户之日起的每一笔交易(事件)。相反,我们有该月新交易(事件)的期初余额(快照)。这样,"MonthEndProcessed" 事件很可能就是一个快照。

我也不真的相信如果快照包含错误则无法修复的论点,因为事件流是不可变的。如果您的事件包含错误会怎样?你能不修吗?理想情况下,这些错误不应进入生产系统,但如果出现,则应予以修复。无论如何,对我而言,不变性与与系统的 典型 交互有关。一旦事件发生,我们通常不会对其进行更改。

在某些情况下,返回并将某些事件更改为较新版本甚至可能是有益的。这些应该保持在最低限度,最好避免,但在某些情况下可能是务实的。

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

My question is whether or not I should produce a specific event for snapshotting, so something like "WarehouseStateSnapshotted".

"It depends".

您应该查看快照的参考文献是 CQRS Documents,作者是 Greg Young。它是相对较旧的 2010 年,但作为快照概念的简单介绍。

异步生成快照并将它们存储在事件流之外没有错。

您可以为快照过程使用任何合理的触发器;您不一定需要流中的事件。 "Snapshot every 100 events" 或 "Snapshot every 10 minutes" 或 "Snapshot when the admin clicks the snapshot button" 都是可行的。

有些域具有自然的韵律,域本身可能会暗示一个快照——想想 "closing the books on the fiscal year"。

我对将域不可知 "make a snapshot" 消息放入事件流有点怀疑 - 我认为让聚合负责快照节奏是不合适的。它没有损坏,但确实感觉有点像用不同的关注点重载事件流的语义。