问题描述
我有一个带有axon 4.4.2的spring boot maven多模块项目,项目的层次结构如下:
application --core --command-side ----command-side-axon ----command-side-rest --query--side ----query-side-persistence ----query-side-rest
我有一个创建新目录的示例,如下所示,当我从命令端休息发送请求时,即使查询端持久性崩溃并且未保存数据,它也始终返回一个ID作为响应。在数据库中。在这种情况下,我该如何处理交易?我想当查询端持久性崩溃时,事件不会保存在事件库中,并且会引发异常。
命令端按钮
@PostMapping
public String save(@RequestBody Catalog catalog) {
return (String) commandGateway.sendAndWait(new CreateCatalogCommand(catalog));
}
命令端轴突
@CommandHandler
public void handle(CreateCatalogCommand cmd) {
apply(new CatalogCreatedEvent(cmd.externalId,cmd.name));
}
@EventSourcingHandler
@Order(1)
public void on(CatalogCreatedEvent evt) {
this.externalId = evt.externalId;
}
查询侧持久性
@EventHandler
@Transactional(propagation = Propagation.required)
@Order(2)
public void on(CatalogCreatedEvent event) {}
解决方法
我想可以就您的主要问题向您提供一些信息:
我想当查询侧持久性崩溃时,该事件不会保存在事件库中,并且会引发异常。
好吧,这实际上意味着您完全根本不想使用CQRS。 CQRS代表的是您的命令模型(例如,处理命令并发布事件的集合)和查询模型(例如,处理事件的类,这些事件会更新您的模型)的隔离。
将这两种方法隔离可以为您带来好处,您可以针对两种情况优化模型。此外,执行操作(即命令)的请求不再受后续事件是否实际上可以更新查询模型的影响。最重要的是,如果您正在执行CQRS,则不应该这样做!具有这种精确的隔离意味着您可以在需要时 重新创建查询模型,而无需执行命令。
因此,从本质上讲,您的事件存储区是因为您可以将 all 模型作为基础的单个模型,并且彼此独立。这就是为什么在进行CQRS时使用事件与Event Sourcing可以很好地结合使用的原因(该事件状态根据 it 发布的事件来重新创建命令模型)。
那么,我的建议是?我会接受这样一个事实,即如果更新您的查询模型的事件处理失败,则该事件仍会发生。基本上,它并没有改变您的系统已决定发布该事件的事实,所以就这样吧。
如果您确实希望在单个事务中拥有命令模型和查询模型,则仍然可以通过使用Axon中的SubscribingEventProcessor
仅 来实现。同样,我会与您的团队/企业讨论这是否真的是您所需要的。
请查看AxonIQ的“学习” page上的一些帖子,以了解为什么CQRS,DDD和事件源可以为您带来好处。
希望这可以让我们了解Aymen的情况!