CQRS - 一个命令触发其他命令/由其他命令组成

CQRS - One command triggering other commands/ being composed of other commands

一个命令可以触发CQRS中的其他命令或由其他命令组成吗?

我想知道的具体情况是我有一个 'CreateAppointmentNote' 命令为现有约会创建注释。我还有一个创建约会的 'CreateAppointment' 命令(没有注释)。

我需要添加功能,如果 'CreateAppointment' 命令中使用的对象具有注释值,那么它也需要创建注释。 'CreateAppointment'命令可以调用'CreateAppointmentNote'命令来做这个吗?

这背后的最终目标是让对约会 POST 端点的一次调用能够添加注释,而不是在最初创建具有注释的约会时也必须调用另一个端点来获取注释。

我知道我可以调用约会命令然后调用注释命令,但是如果将约会添加到数据库成功但注释添加失败,这可能会让我获得奇怪的部分成功。

我只是想找出在 CQRS 中干净地执行此操作的正确方法,并尽可能避免将代码从一个命令复制到另一个命令。

约会和笔记有什么关系?它们是同一聚合的一部分吗?如果是,您的任命是否作为聚合根(因此负责 "protecting" 注释)?成功创建约会但未成功创建备注是否会使交易无效?

如果注释是创建新约会的事务的基本部分并且是约会聚合的一部分,那么它们反映了一起变化的事物并且可能是同一命令的一部分; CreateAppointment 可以包含任何与注释相关的属性作为创建请求的一部分,然后 AddNoteToAppointment 可以管理现有约会的后续注释。

如果它们是完全独立的 services/aggregates 并且必须一起创建才有效,那么您可以考虑像 the saga pattern 这样的东西,它可以确保整个交易通过或回滚,但可能值得看看您的聚合边界,看看它们实际上是否应该在单个聚合下。

引用 cqrs.nu:

I know aggregates are transaction boundaries, but I really need to transactionally update two aggregates in the same transaction. What should I do?

You should re-think the following:

  • Your aggregate boundaries.
  • The responsibilities of each aggregate.
  • What you can get away with doing in a read side or in a saga.
  • The actual non-functional requirements of your domain.

If you write a solution where two or more aggregates are transactionally coupled, you have not understood aggregates.