命令和查询端之间的轴突事务管理器

问题描述

我有一个带有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的情况!