【问题标题】:How to process aggregates in batch and publish only one event in DDD?如何批量处理聚合并在 DDD 中只发布一个事件?
【发布时间】:2015-09-02 10:12:40
【问题描述】:

我在开发我的域时遇到了一个情况,希望有人可以帮助我解决。

在我当前的项目中,我需要从缓存中读取一种类型的所有存储聚合(比如说 ClientAggregate)。我从服务层读取聚合,然后,对于它们中的每一个,我为当前聚合获取一个锁以进行一些处理,然后将其保存回来。业务逻辑要求只发送一个事件,其中包含有关已修改聚合的信息,因为侦听此事件的系统是遗留系统并且已经定义了模式。

我遇到的问题是,由于这个锁定过程,我发送的事件是从服务层而不是域发送的。该逻辑要求在一个事件中发送所有已修改的聚合信息。因为出于性能原因我需要单独锁定聚合,所以我无法将所有聚合传递给域服务来处理那里的逻辑并生成事件。我的选择是直接从域服务内部锁定,然后我会将基础架构逻辑泄漏到我的域中。

因此,在我当前的解决方案中,该服务包含用于迭代聚合并生成事件的域逻辑。在域服务中执行此操作,逻辑将在域中,但需要移动锁定机制。第三种选择是为每个修改过的聚合发布一个事件,但是应该有一些东西能够消耗它们,以某种方式等待整个过程完成,所以我不知道这是否是一个选项。

【问题讨论】:

  • 你真的需要悲观锁吗?无论如何,对于聚合的批处理,也许您应该研究 sagas。
  • 存储仅基于缓存。如果我不锁定,则在我尝试读取对象以进行此处理时,另一个线程可能会从对象中删除某些内容。我真的不知道如何使用 sagas 和聚合。我对 sagas 的了解是,您有一个协调员,他向不同的服务发送消息,最后发送提交确认或补偿消息,以防出现错误。您如何在同一个服务中使用它来协调聚合?

标签: java domain-driven-design


【解决方案1】:

业务逻辑要求只发送一个事件,其中包含有关已修改聚合的信息,因为侦听此事件的系统是一个遗留系统并且已经定义了一个架构。

对我来说,这听起来不像是真正的领域事件。如果是这样,那么您尝试以这种方式构建系统的原因将是因为域是这样工作的,而不是“因为侦听此事件的系统是旧系统”。

所以你应该这样做:

  • 从服务层控制整个批处理,就像您已经拥有它一样。
  • 如果处理每个聚合的逻辑是域逻辑,则将其提取到域服务中并从服务层调用它。
  • 该域服务也可以发布域事件,如果域需要
  • 完成后从服务层发布“finished*”事件。这不是领域事件。

【讨论】:

  • 我不确定该事件是否不属于该域。这是我第一次处理更改一批聚合,所以也许这就是原因。业务逻辑要求,给定特定事件,应分析所有聚合以检查它们是否符合特定条件,然后进行更新。然后,应该发送一个事件,其中包含有关已修改聚合的信息。只是必须转换此事件以匹配旧模式。我的问题是锁定聚合。域应该发送事件,但为此我需要从域服务内部锁定。
  • 如果锁定是能够发送域事件的先决条件,我会说你有一个更基本的设计问题。为什么不能只锁定服务层并从领域层发布事件?
  • 这就是我正在做的事情,我锁定服务并从锁定内部调用域。但是这是针对每个聚合单独完成的,因为我可能有 100000 条记录。我无法锁定所有记录前期因为它会杀死应用程序。但是,一个编排是服务层来跟踪修改的那些。要从域中执行此操作,我需要从域服务内部锁定以跟踪更改。
  • 所以一切都在它所属的地方!事务控制属于服务层,所以“编排”在那里很好。
  • 嗯,如果我没有这个锁定问题,我想我会从域发送消息。对我来说,应该处理对每个聚合的调用并发送事件的应该是域服务,因为它在需求中以这种方式指定。然后,基于此事件为遗留系统构建消息的人应该是使用该事件的基础设施侦听器。但我无法得出任何其他选择,所以我想这是我能得到的最接近的选择。感谢您的提示!
猜你喜欢
  • 2021-07-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-13
  • 1970-01-01
  • 1970-01-01
  • 2023-02-26
  • 1970-01-01
相关资源
最近更新 更多