【问题标题】:Conditional `create` commands within a CQRS architectureCQRS 架构中的条件“create”命令
【发布时间】:2018-11-28 22:13:59
【问题描述】:

我会简化我的问题:

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

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

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

这些事件将应用于Light Aggregate,而持久化的投影将是state of the light

到这里为止一切顺利。

但是因为没有输入:create light,我无法从中生成CreateLightCmd。我只能在收到带有新的lightIdlightOn 输入时调用CreateLightCmd,以创建Light Aggregate,然后在其上应用TurnLightOnCmd

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

谢谢

【问题讨论】:

  • 我只能在收到带有新 lightId 的 lightOn 输入以创建 Light Aggregate 然后在其上应用 TurnLightOnCmd 时调用 CreateLightCmd - 这是由你的背景?看起来非常复杂。
  • 这不是一个约束,但聚合的创建应该通过显式命令完成,这就是我建议CreateLightCmd的原因。
  • 我现在正在尝试直接调用事件存储来检查lightId 的唯一性。这样至少命令端和查询端是​​分开的。
  • 我的意思是,客户端在创建 Light 时是否绝对必须提前知道 ID,以及为什么首先将 TurnLightOnCreateLight 关联起来?

标签: java domain-driven-design cqrs eventsource axon


【解决方案1】:

是否可以从命令端调用查询端以通过 id 检查光是否存在,然后在需要时先调用 CreateLightCmd?

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

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

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

但是:创作模式很奇怪

当我们尝试查询一个我们以前没有见过的标识符的历史时,我们会得到一个空值,或者一个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)
}

【讨论】:

  • 我最终实现了类似你建议的东西。如果存在具有指定 lightId 的任何事件,我在 EventStore 中检查,然后调用 CreateLightCmd 或 TurnLightOnCmd。
【解决方案2】:

看看 Udi Dahan 的开创性帖子“不要创建聚合根”[0]。重点是:

  • 不要创建聚合根
  • 始终获取实体

这意味着当您发出命令时,您应该始终拥有一个聚合,其中包含初始化为默认状态的实际聚合根实体。在您的情况下,默认状态是“关灯”。您在此灯上执行命令,现在它处于“灯亮”状态。现在将它保存到数据库并创建它。除非您的域关心 LightCreatedEvent,否则您不需要对其建模。

[0]http://udidahan.com/2009/06/29/dont-create-aggregate-roots/

【讨论】:

    猜你喜欢
    • 2013-03-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-08
    • 1970-01-01
    • 2018-09-02
    • 2011-05-25
    相关资源
    最近更新 更多