在 Axon 中投影 @AggregateVersion
Projecting @AggregateVersion in Axon
我在聚合中使用注解 @AggregateVersion
来处理乐观并发。为了在请求中接收此版本,任何提出请求的人都需要首先从我的视图投影中获取当前版本。是否有一些标准方法来投影此版本字段(因为我猜,这不应该包含在事件 DTO 中)?
到目前为止,我唯一能想到的就是在投影中计算投影事件,并在每次投影一个事件时增加版本+1。
您可以将 MetaData
添加到消息(命令和事件)中。
可以选择向元数据添加一些信息以防止乐观并发问题。
您可以发送如下消息:
MetaData metaData = MetaData.with("mykey", "myvalue");
metaData.put("lockVersion", currentVersion);
commandGateway.send(new GenericCommandMessage(doSomethingCommand, metaData));
在聚合命令处理程序中,您可以执行如下操作:
@CommandHandler
public handle(DoSomethingCommand cmd, MetaData metaData, @MetaDataValue("mykey") String someValue) {
// ... version check between aggregateVersion and lockVersion
MetaData eventMetaData = MetaData.with("lockVersion", aggregateVersion);
AggregateLifecycle.apply(new GenericEventMessage(new SomethingDoneEvent(), eventMetaData));
}
和事件处理中的同类逻辑:
@EventSourcingHandler
public void on(SomethingDoneEvent evt, MetaData metaData) {
// ...
}
免责声明:我是 Axon 框架和事件溯源的新手,所以这可能不是一个好的选择and/or有更好的方法可以做到这一点。
Jasper 的 MetaData
建议可以帮助您解决这个问题,但还有更简单的解决方案。
Axon 使用 ParameterResolvers
的概念(遗憾的是只有非常简短的描述 here, but in more depth here)来解决诸如 command/event/query、MetaData
或 MetaDataValue
之类的问题.但是,您也可以让框架解析事件源聚合 中的序列号是 聚合版本。您可以通过在事件处理函数中添加 @SequenceNumber
带注释的 Long
参数来实现。
因此,您可以像这样编写事件处理程序:
@EventHandler
public void on(YourEvent event, @SequenceNumber Long aggregateVersion) {
// Update the query model And the aggregate version
}
话虽如此,这显然需要您在事件处理组件中处理聚合中的 all 事件,以便能够相应地更新版本。幸运的是,Axon 会识别您是否处理了事件负载的父 classes。因此,如果您定义事件 class 层次结构,确保来自给定聚合的所有事件实现 interface MyAggregateEvent
。因此,您可以像这样编写一个事件处理程序来涵盖所有剩余的事件,仅用于聚合版本更新,否则您不会对此感兴趣:
@EventHandler
public void on(MyAggregateEvent event, @SequenceNumber Long aggregateVersion) {
// Update the aggregate version only
}
希望对您有所帮助!
P.S。我刚刚注意到参考指南的 Handling Events page 确实说明了 @SequenceNumber
注释。
我在聚合中使用注解 @AggregateVersion
来处理乐观并发。为了在请求中接收此版本,任何提出请求的人都需要首先从我的视图投影中获取当前版本。是否有一些标准方法来投影此版本字段(因为我猜,这不应该包含在事件 DTO 中)?
到目前为止,我唯一能想到的就是在投影中计算投影事件,并在每次投影一个事件时增加版本+1。
您可以将 MetaData
添加到消息(命令和事件)中。
可以选择向元数据添加一些信息以防止乐观并发问题。
您可以发送如下消息:
MetaData metaData = MetaData.with("mykey", "myvalue");
metaData.put("lockVersion", currentVersion);
commandGateway.send(new GenericCommandMessage(doSomethingCommand, metaData));
在聚合命令处理程序中,您可以执行如下操作:
@CommandHandler
public handle(DoSomethingCommand cmd, MetaData metaData, @MetaDataValue("mykey") String someValue) {
// ... version check between aggregateVersion and lockVersion
MetaData eventMetaData = MetaData.with("lockVersion", aggregateVersion);
AggregateLifecycle.apply(new GenericEventMessage(new SomethingDoneEvent(), eventMetaData));
}
和事件处理中的同类逻辑:
@EventSourcingHandler
public void on(SomethingDoneEvent evt, MetaData metaData) {
// ...
}
免责声明:我是 Axon 框架和事件溯源的新手,所以这可能不是一个好的选择and/or有更好的方法可以做到这一点。
Jasper 的 MetaData
建议可以帮助您解决这个问题,但还有更简单的解决方案。
Axon 使用 ParameterResolvers
的概念(遗憾的是只有非常简短的描述 here, but in more depth here)来解决诸如 command/event/query、MetaData
或 MetaDataValue
之类的问题.但是,您也可以让框架解析事件源聚合 中的序列号是 聚合版本。您可以通过在事件处理函数中添加 @SequenceNumber
带注释的 Long
参数来实现。
因此,您可以像这样编写事件处理程序:
@EventHandler
public void on(YourEvent event, @SequenceNumber Long aggregateVersion) {
// Update the query model And the aggregate version
}
话虽如此,这显然需要您在事件处理组件中处理聚合中的 all 事件,以便能够相应地更新版本。幸运的是,Axon 会识别您是否处理了事件负载的父 classes。因此,如果您定义事件 class 层次结构,确保来自给定聚合的所有事件实现 interface MyAggregateEvent
。因此,您可以像这样编写一个事件处理程序来涵盖所有剩余的事件,仅用于聚合版本更新,否则您不会对此感兴趣:
@EventHandler
public void on(MyAggregateEvent event, @SequenceNumber Long aggregateVersion) {
// Update the aggregate version only
}
希望对您有所帮助!
P.S。我刚刚注意到参考指南的 Handling Events page 确实说明了 @SequenceNumber
注释。