transactions - 如何处理跨有界上下文的长时间运行的流程/传奇用例

标签 transactions domain-driven-design eventual-consistency

我目前正在研究这个用例:

  1. 预算分配给组织部门
  2. 迈克使用预算订购了一件商品
  3. Jane 对此订单表示同意,并验证它。此操作会引发以下后果:
    1. 检查预算余额,看看我们是否可以接受此订单:如果失败,请通知 Jane。
    2. 预算减少至订单金额
    3. 订单状态从 WAITING_VALIDATION 更改为 VALIDATED
    4. 向 Jane 显示一条成功消息

其他用例信息:

  • 对于我们的用户来说,从 3.1 到 3.4 的步骤必须是实时的。 Jane 单击按钮并等待答案:确定或不确定并且订单状态已验证

我在想:

  • 预算是有界上下文。
  • 排序是另一个有界上下文。
  • 验证步骤将更改 2 个聚合根,这似乎是错误的。并添加耦合。如果我们需要同时更新另一个聚合根(第 3 步,例如为商品创建会计折旧分录)。
  • 为了实现实时性,我们可以使用 XA 事务(例如 SQL + 消息传递),但我想避免使用它(而且我当前的技术堆栈不允许我使用 XA 事务)。

看来我们可以使用最终一致性来实现这种用例: - 订购服务要求预算服务处理 processOrder 命令(通过消息传递或 REST):此时订购服务正在等待预算服务。 - 预算服务处理命令(在本地事务中)并向调用者发送 OK/NOK - 预算服务还发送 OrderInBudgetProcessed 事件。 - 订购服务实时收到OK/NOK并通知Jane(但此时订单状态没有改变) - 订购服务处理 OrderInBudgetProcessed 并更新本地事务中的订单状态。

我认为这可行。但是我有一些问题:

  • 在订单状态未更新期间,Jane 无法打印订单并将其发送给供应商。
  • 在订单状态未更新的时间内,我们可以想象Mike想要取消订单。状态仍为“等待”,因此允许“取消”操作。我们必须询问 BudgetService 订单已被处理吗?如果是,那么我们必须询问所有使用命令的服务的状态。我们可以使用 saga 或协调器之类的东西吗?
  • 采取补偿措施似乎需要大量工作......

一些问题:

  • “订单验证”由 2 个步骤组成,主要由预算上下文或订单上下文处理? (在我看来,主要事件是预算减少,所以我正在考虑预算背景)。你觉得符合逻辑吗?
  • 您对这种用例有何看法?太复杂?
  • 你如何处理这个问题?
  • 我错过了什么同时拥有干净的代码(避免在同一事务中更新/同步所有对象的服务)和满意的域用户(Mike/Jane)。

有错误的地方请指正:)

期待您的来信。

弗朗索瓦

最佳答案

我曾经遇到过类似的情况,最终的做法是这样的:

两个有界上下文:库存和订购

当订单需要履行时,订购上下文接受命令,将订单从 WAIT_FULLFILL 更新为 FULLFILLING 并发出 OrderFullfillingRequiredEvent。

库存上下文订阅此事件并更新库存,然后发出带有订单跟踪 ID 的 InventoryUpdatedEvent。

排序上下文订阅后一个事件并将订单从 FULLFILLING 更新为 FULLFILLED。

如果有人想在此期间取消订单,订单将会被拒绝,因为状态现在为 FULLFILLING,这表明订单正在等待响应。

相当于您的用例,我认为它将添加一个中间状态 WAITING_VALIDATION-->VALIDATING-->VALIDATED。

并且仍然需要一些补偿,因为 InventoryUpdatedEvent 可能永远不会到来。最烦人的问题是在用户界面方面,也许你需要轮询后端以使其看起来像实时的。

关于transactions - 如何处理跨有界上下文的长时间运行的流程/传奇用例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26312656/

相关文章:

Azure服务总线: How to achieve eventual consistency when a subscriber goes down

Cassandra - 一致性顺序

unicode - PYTHON3(不是 PYTHON2)TypeError : Won't implicitly convert Unicode to bytes; use . encode()

mysql - Django 1.5 Mysql 5.5(InnoDb)事务在异常中不回滚

c# - DDD : Referencing non root Entities by Id from other Aggregates?

.net - 静态方法 : When and when not

java - 如何将消息保存到数据库并将响应发送到主题最终一致?

java - 如何模拟数据库故障以测试 Java 中的两阶段提交

java - 让事务包装 App Engine 中的每个数据存储区事件(读取和写入)是否存在任何性能风险?

mysql - 如何使用流畅的 api 在 EF6 中映射值对象标识?