java - CQRS 架构中的条件 `create` 命令

标签 java domain-driven-design cqrs eventsource axon

我会简化我的问题:

我的 LightsState API 可以接收 2 种类型的输入:lightOn {lightId: ##}lightOff {lightId: ##}。 (AMQP 输入,但与此处无关)

这些输入可以很好地转换为 2 个命令:TurnLightOnCmdTurnLightOffCmd

这些命令将创建 2 个事件:LightTurnedOnEventLightTurnedOffEvent

这些事件将应用于Light Aggregate,持久投影将是灯光状态

到这里为止一切都很好。

但是因为没有输入:create light,我无法从中创建CreateLightCmd。当我收到带有新 lightIdlightOn 输入来创建 Light Aggregate 时,我只能调用 CreateLightCmd然后还应用 TurnLightOnCmd

我不知道如何处理这个问题并遵循良好的 CQRS 实践。 是否可以从命令端调用查询端来检查 id 是否存在灯光,然后在需要时首先调用 CreateLightCmd ? 或者我应该从命令端进行数据库查询并保持命令端和查询端解耦? 或者还有其他解决方案吗?

谢谢

最佳答案

Is it ok to call the Query side from Command side to check if light exists by id and then invoke CreateLightCmd first if needed?

并非如此 - 这会引入竞争条件,其后果可能不会让您高兴。

回顾:DDD+CQRS+ES 在架构上与单独的 DDD 非常相似。基本概念是我们将信息保存到我们的存储设备(也称为“数据库”)中。该模型在从数据库加载当前状态的进程中运行,使用命令计算新状态,然后将该新状态存储在数据库中。

当我们进行事件溯源时,同样的模式也适用 - 我们从用于写入的数据库中读取历史记录,计算新事件,并将这些事件附加到历史记录中。

但是:创建模式很奇怪

当我们尝试查询以前从未见过的标识符的历史记录时,我们将得到 null 或 None 或其中没有事件的历史记录,或类似的东西。

令人惊讶的是:这很好

对于您的用例,您不一定需要 CreateLightCmd - 相反,您希望在获得其他命令之一时生成一个新的 LightCreatedEvent应该隐式地创建光。

伪代码:

TurnLightOn (cmd) {
    history = getHistory(cmd.lightId)
    if (history.isEmpty) {
        history.append(LightCreatedEvent.from(cmd))
    }
    history.append(LightTurnedOnEvent.from(cmd))
    save(cmd.lightId, history)
}

关于java - CQRS 架构中的条件 `create` 命令,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53528912/

相关文章:

domain-driven-design - .NET 的 DDD - 是否有可用的通用基础设施库?

domain-driven-design - 在 CQRS 中,如何将聚合上允许的方法列表传达给 UI?

java - OpenLdap 服务器,Spring ldap 用户绑定(bind) (inetOrgPerson) 没有这样的对象

java - 重写 Hashtable.contains() java 时出现 StackOverflowError

domain-driven-design - CQRS-如何为场景执行系统建模

domain-driven-design - 域模型和EF Core模型

entity - 汇总一个实体

domain-driven-design - 如何为在一个上下文中是聚合根但在另一上下文中不是聚合根的实体编写命令?

java - apache上传文件大小覆盖org.apache.commons.fileupload.FileUploadBase

java - JTable:WAITING根据用户输入选择行