Domain driven design 使用事件源时使用聚合版本号为幂等数

Domain driven design 使用事件源时使用聚合版本号为幂等数,domain-driven-design,cqrs,event-sourcing,idempotent,Domain Driven Design,Cqrs,Event Sourcing,Idempotent,使用DDD、CQR和事件源时,消息可能会重新发送或无序发送 我不太关心命令消息,因为用户会立即知道它是否成功。我关心的是事件。如果将聚合版本号附加到事件,我们可以使操作幂等吗?例如: class Person { public function apply(PersonNameUpdated event) { if (version_ + 1 != event.version) { name_ = event.name; +

使用DDD、CQR和事件源时,消息可能会重新发送或无序发送

我不太关心命令消息,因为用户会立即知道它是否成功。我关心的是事件。如果将聚合版本号附加到事件,我们可以使操作幂等吗?例如:

class Person {
    public function apply(PersonNameUpdated event) {
        if (version_ + 1 != event.version) {
            name_ = event.name;
            ++version_;
        }
    }
    private String name_;
    private Integer version_;
}
我不太关心命令消息,因为用户会立即知道它是否成功

您可能应该关注命令消息,因为这些消息实际上会导致记录簿发生更改。是的,快乐之路很容易,但是当用户的命令未被确认时,您希望用户做什么

我关心的是事件。如果将聚合版本号附加到事件,我们可以使操作幂等吗

请记住,事件源实体是从历史中加载的,而不仅仅是经过的事件(即订阅)。您将从记录簿中加载这些实体,因此将向您提供确切的历史记录。您不必担心事件的变化,因为它们是不可变的。类似地,您不必担心历史记录的更改,因为历史记录只是附加的

换句话说,您的事件源实体支持
apply(event)
方法,您根本不需要保护它,只需按顺序加载事件

另一种方法是:实体的历史记录作为
文档消息
传递,而不是作为
事件消息序列
传递

对于从多个事件历史中收集的预测,关注点类似

如果您的实体正在侦听/订阅一些其他实体事件(即,您的实体是一个事件处理器),那么您需要担心幂等性。注意,在这个用例中,事件有两种不同的上下文——事件处理器自身历史中的事件(即,描述事件处理器状态变化的事件)和处理器正在响应的事件。也就是说,您已经应用了
apply(Event myStateChanged)
vs
when(Event something happendsomewhere)

对于前者,您不必担心幂等性(见上文);通过在自己的历史记录中跟踪事件,确保对事件做出一次反应。您的处理器可能是一个状态机(因此事件自然是幂等的),或者您可以跟踪订阅的事件的事件ID,然后确保您不会做出多次反应,等等


奇怪的是,有些地方确实出现了“聚合版本”——它们在命令处理程序中。两种常见形式:首先,命令可能针对要应用的聚合的特定版本(立即解决幂等问题);其次,您将看到对版本号的跟踪,以防止并发修改。

当从事件存储中读取事件时,它们应该已经按照正确的顺序以及正确的版本号进行了读取。在这种情况下,这种检查不是多余的吗?也许你可以在你所面临的问题上做一些扩展。