Saga,存储聚合状态的位置

时间:2017-04-21 20:37:05

标签: domain-driven-design saga

我是传奇的新手。

这是一个简单的场景:

  1. 用户点击"创建订单" :创建订单(首先保持其状态= NEW)
  2. 用户完成订单后,点击保存 - >现在状态已提交
  3. 当另一个检查订单并对其进行验证时,必须进行处理。只有在调用其他服务并给予其GO时,该订单才有效。
  4. 整个工作流程为:

    • NEW - > SUBMITTED
    • 来自SUBMITTED的用户可以取消提交,订单会切换回NEW
    • 验证可以将订单状态设置为VALIDATEDREJECTED
    • 如果REJECTED原始用户必须修改订单,然后再将其置于验证之前。

    所以我需要避免在NEW正在进行时订单可以回滚到VALIDATION

    我的问题是,对于第3步,最好是:

    • 将订单状态更新为PENDING,引发事件并启动一个传奇(具有自己的状态以及流程和业务流程的编排)?
    • 从订单聚合中删除状态并将其放入传奇(所以传奇从步骤1开始)?该传奇被命名为OrderSaga并封装了从开始到结束的所有过程,而不仅仅是需要外部服务的部分,即分布式事务。
    • 别的什么? (链接到博客或Google群组邮件赞赏)

    感谢

1 个答案:

答案 0 :(得分:1)

DDD与域名有关,因此首先您需要了解业务需求。那么,让我们看看有哪些规则:

  1. 可以创建新订单
  2. 创建的订单可以被提交,但经过验证后
  3. The validation process可能需要一些时间,可以取消。如果取消,则可以再次提交订单
  4. The validation process可以拒绝订单或接受订单
  5. 如果订单被拒绝,则可以在更正后再次提交
  6. 如果订单被接受,则会将其发送到下一个流程,但无法提交或更正。
  7. 话虽这么说,我会将两个流程分开(订单创建+创建和订单验证)。另外,我会在OrderAggregate上保留一个状态属性,用于强制执行其不变量。状态可以是:

    1. new:创建订单或取消验证或拒绝订单后
    2. submitted:提交验证后
    3. sent:验证过程接受后。
    4. 如果您需要附加行为, 应该仅添加 新状态。

      OrderValidationSaga还具有内部状态,用于跟踪从外部服务收到的外部响应。我们假设我们需要使用两个外部服务。状态将是具有两个属性的对象:service1IsOkservice2IsOk。当任何服务表明订单无效时,无论内部进度如何,saga都会拒绝订单并重置其内部状态。当服务说OK时,saga在内部将其标记为OK,然后检查所有服务是否正常。如果它们没问题,它会告诉聚合发送订单。然后聚合将订单标记为sent并发出事件。如果/当进程被取消时,saga将重置其内部状态。

      请注意,如果您使用CQRS,则通过发送命令和引发事件来完成所有状态更改。该传奇将订阅事件并将相应的命令发送到聚合。

      有一篇很好的文章here