【问题标题】:DDD handling Aggregate updates over timeDDD 处理随时间推移的聚合更新
【发布时间】:2019-02-18 17:46:34
【问题描述】:

使用事件溯源,我有一个域,其中的聚合应该不时更新。当我创建一个聚合时,我有一个到期时间(这可以是任意的),在那之后我必须更新实体的一些属性。 (这也可以使用 UpdateCommand 强制执行。)我想到的过程很少:

  1. 创建聚合后,我将聚合 ID 和到期时间存储在 RDBMS 中。
  2. 在 cron 作业中,我在数据库中查询过期的聚合,并提交 UpdateCommand

其他包括从读取端发出更新命令(或事件?)。 使用 saga 来协调更新,这与第一个类似。但无论哪种方式,我都必须存储到期时间。

所以,我必须存储事件并在写入端以事务方式写入数据库。但是,我不确定为写入端 (?) 创建一个 读取端是否是 DDD 世界中的正确解决方案,或者它是否适用?有哪些推荐的解决方案?

【问题讨论】:

    标签: domain-driven-design event-sourcing aggregateroot


    【解决方案1】:

    我还需要在一段时间后运行一些命令。

    例如,我需要在 1 年后发出 ContractExpiredEventContractAggregate 决定何时但通常是 1 年)。问题是聚合必须是决定何时以及执行什么命令的那个,所以这是一个域问题而不是基础设施问题。

    我是怎么做到的?我受到Udi Dahan's video 的启发,他在其中介绍了Timeout 一词。长话短说,Aggregate 请求在一段时间后向自己发送命令。它通过从命令处理程序产生它来做到这一点。底层 CQRS 框架获取 scheduled command 并将其保存在一个特殊的存储库中。然后,cron job 在时间到时处理所有预定的命令。

    【讨论】:

    • 我要看那个视频。存储预定的命令似乎很好。但是你所说的“聚合必须是决定何时以及执行什么命令的那个”是什么意思?执行命令的不是客户端吗?我主要使用这个流程:danielwhittaker.me/2014/10/02/…
    • @DavidSzalai 我使用 cqrs.nu 样式。长话短说,Aggregate 处理命令和 yield 事件。
    • 哦,我明白了,我以前看到过(我认为像 Axon 这样的框架使用它),但对我来说,使用单独的命令处理程序一开始似乎更清楚
    • @DavidSzalai 无论如何,答案都适用。
    【解决方案2】:

    ES和DDD的兼容性很好。

    但是,我不确定为写入端 (?) 创建读取端是否是 DDD 世界中的正确解决方案,或者它是否适用?

    是的,在您的情况下,它是域聚合的一部分(如果您谈论在写入端存储到期时间)。

    所以,我必须存储事件并在写入端以事务方式写入数据库。

    我建议你使用 saga 写入数据库。

    【讨论】:

      【解决方案3】:

      John Carmack, 1998:

      如果您不将时间视为输入值,请考虑它直到您这样做——这是一个重要的概念

      您应该寻找的模式是现实世界(时间所在的地方)告诉聚合当前时间,聚合决定是否自行过期

      有了这个模式,你可以使用任何你喜欢的策略来安排什么时候现实世界告诉聚合它是什么时间。

      您不需要在聚合中立即一致的调度,您只需要一些幂等消息处理和“至少一次”传递过程。

      聚合有一个方法,如果有必要,可以根据当前时间而不是盲目地进行更新。有时我必须从存储中获取正确的聚合,调用该方法并将更改存储回来(如果有),或者稍后重试,对吗?

      是的,这是正确的想法。

      请注意,如果您在过期时间之后调用该方法两次,第一次调用将加载历史记录、附加过期事件并存储更新的历史记录。 second 调用加载历史记录,可以看到聚合已过期,并且在不更改历史记录的情况下退出。

      【讨论】:

      • 哦,我没有考虑过这种方式。因此,聚合有一个方法,如果有必要,可以根据当前时间而不是盲目地进行更新。有时我必须从存储中获取正确的聚合,调用该方法并将更改存储回来(如果有),或者稍后重试,对吗?
      【解决方案4】:

      您还可以使用双时间事件溯源。存储事件时,有两个日期:

      • 事件添加到数据库的日期 (createdAt)
      • 必须应用事件的日期 (validFrom)

      然后按照validFrom 属性定义的顺序应用事件。

      使用它,您可以:

      • “修复过去”通过添加新事件(createdAt = nowvalidFrom = now - x
      • 通过添加新事件(createdAt = nowvalidFrom = now + y)来安排未来的事件

      我建议在 DDD Europe 2018 上观看 Thomas Pierrain 的精彩视频:https://www.youtube.com/watch?v=xzekp1RuZbM

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-01-13
        • 2019-03-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-07-22
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多