DDD处理随时间推移聚合更新

问题描述 投票:2回答:4

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

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

其他包括从读取端发出UpdateCommands(或事件?)。使用saga来协调更新,这与第一个类似。但不管怎样,我必须存储到期时间。

因此,我必须存储事件并在事务上写入写入端的数据库。但是,我不确定为写入端(?)创建读取端是否是DDD世界中的正确解决方案,还是适用?推荐的解决方案是什么?

domain-driven-design event-sourcing aggregateroot
4个回答
2
投票

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

例如,我需要在1年后发出ContractExpiredEventContractAggregate决定何时但通常是1年)。问题是Aggregate必须是决定何时执行什么命令以及执行什么命令的聚合,因此这是一个Domain关注点而不是基础结构问题。

我是怎么做到的?我受到了Udi Dahan's video的启发,他在其中引入了Timeout一词。简而言之,Aggregate要求在经过一段时间后将命令发送给自己。它通过从命令处理程序产生它来做到这一点。基础CQRS框架获取scheduled command并将其持久保存在特殊存储库中。然后,cron job处理所有预定的命令。


1
投票

ES和DDD之间有很好的兼容性。

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

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

因此,我必须存储事件并在事务上写入写入端的数据库。

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


1
投票

John Carmack, 1998

如果你不把时间视为输入值,那么在你做之前要考虑它 - 这是一个重要的概念

您应该寻找的模式是现实世界(时间)告诉聚合当前时间,聚合决定是否自己到期。

有了这种模式,您可以使用任何您喜欢的策略来安排现实世界告诉聚合的时间。

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

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

是的,这是正确的想法。

请注意,如果在到期时间之后两次调用该方法,则第一次调用将加载历史记录,附加到期事件并存储更新的历史记录。第二个调用加载历史记录,可以看到聚合已经过期,并且在不对历史记录进行任何更改的情况下退休。


1
投票

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

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

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

使用此功能,您可以:

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

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

© www.soinside.com 2019 - 2024. All rights reserved.