事件溯源系统的追溯与未来事件

  • Jan Stenberg
  • 张卫滨

2018 年 2 月 22 日

话题:语言 & 开发架构

看新闻很累?看技术新闻更累?试试下载 InfoQ 手机客户端,每天上下班路上听新闻,有趣还有料!

Thomas Pierrain与一家资产管理公司开始一个新项目的时候,其中有一项重要的需求就是能够回到过去,理解当时为什么会做出一些现在看起来很奇怪决策。在最近于阿姆斯特丹举行的DDD Europe 2018上,Pierrain 讨论了他构建事件溯源系统的经历以及所面临的挑战。

这家公司想要构建的系统需要能够提供整个公司业务相关的信息。详细的需求包括能够生成过去特定日期的报告、通过添加回溯(retroactive)事件改变过去的行为以及调度未来的事件。

在开始的时候,42skillz的咨询师 Pierrain 和他的同事在把握业务需求方面遇到了不少的困难,所以他们召开了多次会议和 workshop 以理解领域、需求以及他们真正想要什么。改变过往的原因在于在某些事情发生之后,业务有了新的发现,所以必须要通过添加回溯事件改变他们对世界的认识。调度未来事件的原因在于他们能够知道未来将要实际发生的事件,而他们不想像以前那样错过这些事件。

对于 Pierrain 来说,这个系统采用基于事件溯源(event sourcing)的技术是很合适的选择。但是,改变过往和事件调度的需求让他对这个技术决策产生了怀疑。因此,他咨询了事件溯源社区,来自社区的响应,包括Greg Young的响应,都显示他的决策是正确的。Young 还引用了一篇他在 2014 年所撰写的博客文章:Event Sourcing and Post/Pre Dated Transactions

要使用过往的事件,可以根据需求采用三种投射模型(projections mode):

  • “as at”用于特定日期的结果;
  • “as of”用于特定日期的结果,但是还要考虑到随后的事件可能也要应用回溯;
  • “as of until”用于特定日期的结果,但是还要考虑到随后的事件可能也要应用回溯,这样的事件会追溯到某个特定的日期截止,在此之后的事件不再考虑。

回溯事件有两个日期,一个用于表述事情发生的日期(实际日期),一个用于表述它记录的日期。要生成过往的报告,必须要考虑事件的这两个日期。对于他的需求而言,Pierrain 用到了两个术语:

  • Viewpoint 日期:世界在某个特定时间的状态,采用的是“as of until”模式;
  • Projection 日期:指的是报告的日期。

这意味着如果我们要站在 2017 年 7 月 1 日的视角上,为 2017 年 6 月 1 日生成一份报告的话,将要使用实际日期为 6 月 1 日的事件,以及记录时间不晚于 2017 年 7 月 1 日的事件。举例来讲,MoneyAdded 事件代表了特定日期为某个账号增加钱数的事件。要使用之前的日期生成报告,需要使用如下的逻辑:

  • 添加实际日期和记录日期为 6 月 1 日的事件;
  • 实际日期和记录日期为 6 月 2 日的事件不能添加;
  • 添加实际日期为 6 月 1 日且记录日期为 7 月 1 日的事件;
  • 实际日期为 6 月 1 日且记录日期为 7 月 2 日的事件不能添加。

在创建回溯事件的时候,团队决定采用命令(command)的方式进行创建,因为这些事件有一些必须要执行的业务逻辑,不过 Pierrain 指出,在有些场景下,直接创建事件的做法可能会更好一些。对于未来事件的解决方案是调度一条能够创建事件的命令。

早在 2005 年,Martin Fowler就写过一篇关于临时(Temporal)模式的文章,该文描述了 Pierrain 所经历的相同问题。

DDD Europe 2019的计划已经启动,但是具体的日期尚未确定。

查看英文原文Retroactive and Future Events in an Event Sourced System

语言 & 开发架构