我们正在将轴突集成到我们现有的Spring Boot应用程序中。当前,我们正在使用Axon 4.1.2和Axon Server。
例如,在注册过程中,我们触发一个RegisterCommand
,它由RegisterAggregate
读取并触发RegistrationDoneEvent
。
有两个EventHandlers
正在收听此RegistrationDoneEvent
。分别是RegistrationNeo4jEventHandler
和RegistrationSqlEventHandler
。
没有例外,一切都很好。但是,当发生异常时,假设Neo4JEventHandler
接收到事件,并且发生异常,则SqlEventHandler
窗台被调用,即使SqlEventHandler
仍然看起来一切都回滚了运行成功。
我们如何使SqlEventHandler
完成并提交SqlEventHandler
重试?
其次,如何在失败后完全停止重试该事件?假设我们有四个事件处理程序(HandlerA,HandlerB,HandlerC,HandlerD)侦听SAME事件。如果HandlerC失败,则当我们说修复了基本问题时,我们想触发它进行重试,但还要确保侦听SAME事件的其他处理程序不会重新运行。
以下代码片段包括聚合和事件处理程序。
RegisterAggregate
Neo4JEventHandler
RegistrationSqlEventHandler
@Aggregate
public class RegisterAggregate {
....
@CommandHandler
public RegisterAggregate(RegisterCommand command) {
apply(new RegistrationDoneEvent(command));
}
}
RegistrationNeo4jEventHandler
@Service
@Transactional
public class RegistrationSqlEventHandler {
@EventHandler
@Order(Ordered.HIGHEST_PRECEDENCE)
public void on(RegistrationDoneEvent event) {
....
}
}
我将我的回答分成两个部分,因为您提出的不是一个问题,而是两个问题。首先,让我们谈谈您的问题:
我们如何使
@Service @Transactional public class RegistrationNeo4jEventHandler { @EventHandler public void on(RegistrationDoneEvent event) { .... } }
完成并提交RegistrationSqlEventHandler
重试?
从命名开始,两个事件处理组件(即包含RegistrationNeo4jEventHandler
批注方法的类you写入)已经非常明显地服务于完全不同的查询模型。第一个目标是RDBMS,第二个目标是通过Neo4j更新图模型。
因此,我发现您最终很有可能对这两种功能都有不同的非功能性要求。为了能够对它们进行不同的配置,您将必须为两者使用不同的@EventHandler
实例。事件处理器,负责管理将事件提供给your事件处理程序的技术方面的组件,作为配置诸如异常处理,线程号,批处理大小等内容的位置。>
请注意,事件处理器有两种形式:Event Processor和SubscribingEventProcessor
。可以将它们简短地描述为事件推送和事件拉动机制,后者是默认机制,因为它会进一步隔离。
要为两者配置不同的事件处理器,您可以使用Axon提供的配置API。对于事件处理器,这意味着与TrackingEventProcessor
进行交互。使用它,您可以定义不同的事件处理器,然后将事件处理组件分配给正确的实例。您可以采用的一种简便方法是在两个事件处理组件上添加EventProcessingConfigurer
批注,并在其中添加不同的名称。尤其是在Spring Boot环境中,就配置而言就足够了。
进行此隔离将确保@ProcessingGroup
中的异常情况不会对RegistrationNeo4jEventHandler
产生任何不希望的影响,反之亦然。
第二,让我们转到另一个问题:
第二,如何在失败后完全停止重试事件?
为此,您必须调整事件处理过程的异常处理。关于事件处理组件,Axon派生了两个级别的异常处理:
RegistrationSqlEventHandler
->负责处理由ListenerInvocationErrorHandler
带注释的方法引发的异常。@EventHandler
->负责处理在事件处理器中[[内部ErrorHandler
)并传播异常(使用LoggingErrorHandler
)。FYI,参考指南中的PropagatingErrorHandler
表示事件处理器的错误处理。
在此问题中,您将通过不同的事件处理功能进一步指定案件。同样,如果您不想影响某个事件处理的失败而导致另一事件的问题,则可能需要将这些关注点与不同的事件处理器分开。
不过请记住,如果您要例示的这四个事件处理程序只是在更新查询模型,则后续调用应仅执行相同的操作而没有任何副作用。但是,如果这些事件处理程序执行其他一些(外部)活动,例如发送电子邮件,则绝对可以保证将给定的事件处理组件隔离到一个您不想重试/重播的独立事件处理器中。