在一项交易中创建多个汇总

时间:2019-07-26 11:44:24

标签: entity-framework architecture transactions domain-driven-design ddd-repositories

我的受限上下文(库存)收到一个数量为5的事件。其中5是从仓库中的卡车卸下的托盘数。现在在我的库存BC中,我想创建5个集合(每个托盘1个集合)。如何在我的应用程序层中做到这一点?如果我仅成功创建其中的3个怎么办?我无法过渡创建它们,因为我的持久存储基于文件。我该怎么办?

2 个答案:

答案 0 :(得分:3)

通常的回答是这样的-我们要做的第一件事是将 event 保存在“ TODO”列表中。

我们对该列表的“订阅”需要跟踪,即写下 ,它在待办事项列表中的位置。例如,我们可以将TODO列表视为事件的仅追加序列,而订阅则记下最后一个完全处理的事件的索引。

当订阅运行时,它将查找列表中的第一个未处理事件,并根据您需要的交易次数来进行工作。完成所有工作后,它会更新自己的计数器(另一笔交易),然后继续进行。

如果处理失败,则我们将永远无法完成“写下来”步骤;因此,当我们重新启动它时,它将尝试再次处理同一事件。

要执行此操作,我们需要两个属性:一个是再次运行处理器应为聚合生成标识符的 same 列表,并且处理器知道聚合可能已经存在。创建,并在这种情况下采取适当措施。

因此,在最坏的情况下:我们得到5个托盘的事件。我们创建所有5个新的聚合,然后崩溃,然后再记录事件已被完全处理。该过程重新启动,并开始处理同一事件。它发现已经创建了每个新的聚合,因此这些步骤中的每个步骤都变为空操作。最后,在完成了事件的所有处理后,它记录了事件已完成。

换句话说,我们需要幂等处理。

答案 1 :(得分:1)

您应该将收据事件的记录和五个货盘的生成视为两个独立的交易。

在您的情况下,更改涉及两个聚合,但是理想情况下,您的应用程序服务应尽可能地处理一个聚合。 领域事件是解决此类扩展交易问题的正确结构,无论是在单个BC中的汇总之间还是跨BC。

因此,您的应用程序服务会将五个托盘的接收记录为交易,并使用足够的上下文和数据来冒泡一个域事件(例如PalletsUnloaded)。该事件将作为数据结构传递给消息代理,以供注册该域事件的订阅者检索。

然后,托盘聚合将通过特定于事件的订户捕获事件并以两种方式之一对其进行处理:

  1. 您可以一次创建五个托盘。在事务方面,这种方法有点冒险,因为如果您将文件用作持久性存储,则可能会出现故障,并且可能没有粒度数据来确定确切的问题
  2. 您捕获了事件并创建了五个单独的事件消息(例如CreatePallet),每个事件消息都被提交回消息代理。该事件的订户将接他们并创建托盘记录。您将准确地知道哪一个失败了,以及为什么

第二种方法也更安全,因为如果使用可靠的消息代理(例如RabbitMQ)作为事件的传输机制,则可以将错误的事件发送到死信队列中,或者设置机制以稍后重试处理。您还可以构建一个单独的错误处理流程/视图来处理和处理错误事件。