在事件升级之后和修补之前在事件源中出现无效状态是否可以接受?

时间:2016-06-09 20:05:29

标签: event-sourcing

假设我有一系列持久化事件,根据某些"架构"构建一个有效状态。我已经定义了。

我更改架构并升级事件以反映这一点。

但是,某些状态只能通过升级事件才能生效,我还需要添加更多事件来修补状态以使其完全有效。

首先,这种推理在事件采购方面是否有效?

如果是这样,我如何处理特定版本的状态不再有效的情况?我的意思是这可以接受吗?是否仍然可以为具有无效状态的版本补充水分?如果这是一个写模型并且它不是最新版本,我无论如何都无法修改这个状态,所以也许没什么大不了的?

1 个答案:

答案 0 :(得分:0)

  

但是,某些状态只能通过升级事件才能生效,我还需要添加更多事件来修补状态以使其完全有效。

"补偿事件"通常的术语;记录册中有一个文书错误,所以我们需要在历史记录中添加一个纠正错误的新事件。

  

如果是这样,我如何处理特定版本的状态不再有效的情况?

作为一项规则,您要谨慎,极其谨慎,引入任何阻止您加载无效历史记录的自动验证。记住,国家只是国家;业务规则限制了域允许更改的方式。让破碎的状态可读但破碎是安全的。

特别是,如果您允许加载状态,那么枚举您​​的事件流,测试对象的最终状态,并为产生无效状态的任何流生成异常报告,升级它们是一个简单的练习。对运营商/管理层进行处理等等。

假设您对输入验证合理谨慎,并比较您提出的命令是否与最新已知状态一致(聚合强制执行业务规则,但他们不需要为自己保留这些规则),那么您可以可能会达到错误率足够低,以至于您不需要积极的数据验证。当错误易于检测且修复成本低时,情况尤其如此。

如果不这样做,在任何聚合状态处于无效状态时冻结它们是防止进一步损害的好方法。

但是如果你真的需要国家保持有效,那么你就可以玩补偿事件了。

考虑一下:事件采购的基本模式类似于

History history = repository.getHistoryById(id)

State current = State.SEED

for (Event e : history) {
    current = current.apply(e)
}

这里实际上是一个隐藏的概念,它封装了在将事件传递给状态之前处理事件的逻辑。隐藏,因为null case只是将枚举事件直接传递给目标。

History history = repository.getHistoryById(id)
Historian historian = new Historian();

State current = State.SEED

for (Event e : historian.reviewEvents(history)) {
    current = current.apply(e)
}   

历史学家给你一个放置补偿事件逻辑的地方 - 根据自己的状态,历史学家通过大多数事件,但修复那些知道需要编辑/补偿/编辑的事件

历史学家来自哪里?当然,从历史学家的历史来看,为什么呢。您将事件更正的历史(通常很短)加载到历史记录中,然后让历史记录清理聚合的事件。

如果您需要修正历史学家?它一直都是乌龟!每个流都有一个独特的历史学家;历史数据流的标识符是根据它过滤的流计算的(例如,命名为UUID,允许你这样做)。因此,对于每个流,您检查历史流是否存在;当你找到一个没有的时候,你知道停止搜索并使用空历史数据库,汇总更改,处理最后的事件序列以重新生成真实对象的状态,然后离开。

请注意,我还没有在任何地方看到这个想法的参考实施;它的白板声音,但事实是我已经在我自己的设计中推迟了这个要求。

相关问题