CQRS 是 saga/process 管理器同步执行一组相关命令的最佳方法吗?

CQRS is saga/process manager the best approach for executing a set of related commands synchronously?

我有一个 CQRS .NET Core 服务,目前每个命令都有一个端点。有时一组命令构成系统中的单个操作(例如创建评估),一旦前一个命令将数据提交到数据库(这是因为遗留数据库设计),必须同步执行 3 个左右的命令。

目前这是由客户端处理的,每个命令在它的前一个依赖命令完成后触发(使用承诺)。

值得注意的是,这些命令有时也会单独执行,如果将它们组合成一个命令,最终会变得非常庞大并且很难测试。

我想做的是创建一个单一的端点来管理像我们的创建评估那样的操作,它必须一个接一个地执行以下命令:

  1. 用户创建
  2. 已创建评估
  3. AssessmentRegisteredToClient

我一直在使用 MassTransit saga/state machine/process 管理器,但我对它的研究越多(我的理解也越加深),我觉得它似乎越多喜欢矫枉过正而不是正确的方法(因为这些是命令而不是事件,并且都在一个有限的上下文中)。

流程管理器是否合适?如果合适,MassTransit 状态机实现是否适合?或者我应该查看其他来源?或者我应该只是简单地创建一个端点,一次触发每个命令(即在 ASP 控制器中有这个同步代码)?

澄清一下,UserCreated 不是命令,而是事件。

这里有3个选择:

  • 改为构建反应式系统。所以,在 CreateUser 之后(顺便说一句,这里不是一个很好的语言,因为你从来没有 创建 你的用户,他们在你的系统中注册)你发出 UserCreated,这导致发送命令 CreateAssessment 等的反应。
  • 使用 MT saga 作为进程管理器。如果您需要确保稍微复杂的工作流以您期望的方式完成(或失败),则状态机非常适合。
  • 使用MT快递功能实现分布式事务。您将有一系列的活动、行动和补偿行动(逆转)。

我会亲自分析我的问题,找出在我可以 return 对用户说 "it's ok" 之前我需要做的最低限度的事情。其余的可以在幕后异步完成。与其说是技术,不如说是领域分析。

更新 04/12/2019,回答其中一条评论:

同样,当前应用的术语存在问题。许多消息传递库,如 MassTransit、Rebus 或 NServiceBus,都使用 saga 这个词来表示流程管理器。

使用原始术语,流程经理处理可能存在偏差和并行化的整个流程。另一方面,Sagas 实现了一个 single-flow 过程。当 saga 中的任何一步失败时,之前发生的一切都会使用补偿操作恢复。 sagas 没有编排,因为每个步骤都是独立的,当一个步骤完成时,下一步就会执行。 Sagas 始终是无状态的,如果下一步需要包含一些额外信息,则 saga activity 需要将其放入有效负载。

根据定义,流程管理器是协调器。它从不自己完成工作,而是指示其他组件完成工作。然后,通过监听事件,流程管理器决定流程应该如何流动。 流程管理器可以 启动补偿操作,但它本身并不执行该操作,它指示另一个组件来完成这项工作。为了保持流程的当前状态,流程管理器是有状态的。

因为所有命令都由同一个聚合处理,解决方案是创建第 4 个组合命令,以通用语言命名,包含 3 个命令。在内部,聚合只调用 3 个命令方法,因此没有代码重复。

作为最简单的解决方案,它也被明确,在这个特定的用例中,这些命令在单个事务中按顺序执行:它们都成功或者他们都失败了。

P.S。正如@AlexeyZimarev 指出的那样,这些不是命令而是事件