从聚合中删除引用的项目

Remove referenced items from aggregate

我对以下情况有疑问。假设我们有 2 个域和 2 个聚合。域A和域B是不同的微服务。

  1. 域 A - 产品聚合
  2. 域 B - 店铺聚合

在我们的设计中,我们决定域 A 不了解域 B。在域 B 中,每个商店聚合都有一个或多个产品(可售商品)的引用。

如果我们想要删除产品,那么我们可以将 RemoveProductCommand 发送到域 A - 产品聚合。

商店的商品必须从可售商品列表中删除的更新如何处理?我们想以一种 "transactional" 的方式来做到这一点(只有当它也从所有商店中移除时才标记为已移除)。

我已经考虑过了,我看到了 4 个可能的选项:

  1. 监听商店聚合到 ProductRemovedEvent,然后从商店中删除产品引用。接受这个理论可能导致产品无法移除并且仍然在商店销售列表中的情况。

  2. 在域 A 中创建一个 SAGA 并首先从商店中删除商品,然后再将产品标记为已删除。如果 Saga 处理失败,则应通过向已修改的商店聚合发送一些恢复命令来恢复所有商店状态。要知道哪些商店引用了产品,我们使用查询请求来获取该信息。

  3. 与项目符号 2 相同,但还在产品聚合 (productListedInShopList) 中存储商店信息 (id)。

  4. 其他domain/aggregate定义(例如合并它们)

有什么建议可以解决这个问题吗?

我支持选项 2,但是:

"A don't have knowledge about domain B":方案二提倡B为上游,A为下游(A依赖B因为A发送B 的命令和 A 订阅 B 的事件。此命令和事件是 B 的 API 的一部分),而不是相反。但是,这很好! A和B互不依赖。

另外,我会考虑在Domain B中引入Product的概念,比如ShopProduct。该聚合可以链接到您的商店,以确保 B 域模型中的不变量安全(类似于您的第 3 点)。这将解耦您的限界上下文:ShopProduct 是 Shop 限界上下文理解此 Product 概念的方式。这将使您也可以 运行 仅将域模型 B 作为独立应用程序。

ProductRemovedEvent 会将产品(域 A)置于某种 PENDING 状态,例如,REMOVING,并且此事件将触发 Saga

Saga 将在 Product(域 A)和 ShopProduct(域 B)之间进行通信:

  • 收到ProductRemovedEvent,并发送Command到Shop模型
  • ProductRemovedFromAllShopsSuccessfully 从 Shop 收到,我们向 Product 发送命令以将状态更新为 REMOVED
  • ProductRemovedFromAllShopsUnSuccessfully 从 Shop 收到,我们向 Product 发送命令以将状态更新为某个错误状态或初始状态以进行补偿。 ...