【问题标题】:How do I make sure an aggregate exists before publishing an event?在发布事件之前如何确保聚合存在?
【发布时间】:2018-11-18 06:20:02
【问题描述】:

我正在查看 Wolkenkit API ...但不是 100% 清楚如何知道哪些命令需要聚合 ID,哪些不需要。

据我所知,客户端 api 提供了类似的功能

app.accounting.invoice().issue({
  amount: 1000
});

这对于创建一个新的 invoice 来说很好,但应该不可能运行以下旨在更新现有内容的内容

app.accounting.invoice().update({
  amount: 10
});

我假设这个检查应该进入命令函数,但是我该怎么写呢?

const commands = {
  update (invoice, command, mark) {
    const canInvoiceBeUpdated = // ...

    if (!canInvoiceBeUpdated) {
      return mark.asRejected('...');
    }

    // ... update invoice

    mark.asDone();
  }
};

canInvoiceBeUpdated 检查的内容是什么?

【问题讨论】:

    标签: node.js domain-driven-design cqrs event-sourcing wolkenkit


    【解决方案1】:

    @goloroden 于 2018 年 6 月 8 日在wolkenkit slack 中回答

    我会尝试向您解释:如果您想要一个新的聚合,则省略 ID。因此,例如,继续使用聊天示例,当您想发送新消息时:

    app.communication.message().send({ /* ... */ });
    

    相反,如果您想编辑 现有 消息,例如喜欢它,那么你必须提供消息的ID:

    const messageId = '...';
    
    app.communication.message(messageId).like({ /* ... */ });
    

    在每个命令中,您可能希望检查它是否仅适用于新聚合(我们称之为 构造函数命令)或仅适用于现有聚合。检查这一点的最简单方法是使用聚合的exists 函数,它返回true 用于新聚合,否则返回false。因此,在命令内部,您可以执行以下操作:

    const commands = {
      send (message, command, mark) {
        if (!message.exists()) {
          return mark.asRejected('Aggregate does not exist yet.');
        }
    
        // ...
    
        mark.asDone();
      }
    };
    

    如果您不想每次都手动执行此操作,您也可以为此使用中间件,例如https://github.com/thenativeweb/wolkenkit-command-tools ... 那么前面的示例归结为:

    const { only } = require('wolkenkit-command-tools');
    
    // ...
    
    const commands = {
      send: [
        only.ifExists(),
        (message, command, mark) {
          // ...
    
          mark.asDone();
        }
      ]
    };
    

    请注意,此中间件模块的当前版本是3.0,但在 wolkenkit 2.0 发布之前,您必须使用wolkenkit-command-tools 的版本2.0

    【讨论】:

    猜你喜欢
    • 2017-09-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-22
    相关资源
    最近更新 更多