如何处理轴突框架中saga发送的命令

问题描述 投票:1回答:1

使用传奇,给定事件EventA,传奇开始,它发送一个(或多个)命令。我们如何确保命令发送成功,然后其他微服务中的实际逻辑没有抛出,等等。

让我们举个电子邮件传奇的例子:当用户注册时,我们创建一个发布UserRegisteredEvent的用户聚合,将创建一个传奇,该传奇负责确保将注册电子邮件发送给用户(电子邮件中可能包含验证码,欢迎消息等)。

我们应该使用:

  1. [commandGateway.sendAndWait with try / catch->它会缩放吗?

  2. commandGateway.send并使用截止日期,并使用诸如SendEmailFailedEvent->之类的“失败事件”->要求将命令的“令牌”相关联,以便可以将“ associationProperty”与正确的传奇相关联发送SendRegistrationEmailCommand

  3. 句柄中的
  4. [commandGateway.send(...).handle(...)->我们可以引用MyEmailSaga中的eventGateway / commandGateway吗?如果出错,我们发送事件?或者我们可以从我们的传奇实例中修改/调用方法。如果没有错误,则其他服务已发送了一个事件,例如“ RegistrationEmailSentEvent”,因此传奇将结束。

  5. 使用截止日期,因为我们仅使用“发送”,而不处理可能无法发送的命令的最终错误(其他服务已关闭,等等)

  6. 还有其他东西?

  7. 或所有的组合?

下面如何处理错误? (使用截止日期或.handle(...)或其他)

错误可能是:

  • 命令没有处理程序(没有服务,等等)

  • 已处理命令,但在其他服务中引发了异常,并且未发送事件(在其他服务中未尝试/捕获)

  • 处理命令,引发并捕获异常,其他服务发布事件以通知其发送电子邮件失败(佐贺将接收事件并根据提供的事件类型和数据执行适当的操作->可能是电子邮件错误或不正确存在,因此无需重试)

  • 我错过了其他错误?

@Saga
public class MyEmailSaga {

    @Autowired
    transient CommandGateway commandGateway;


    @Autowired
    transient EventGateway eventGateway;

    @Autowired
    transient SomeService someService;

    String id;
    SomeData state;
    /** count retry times we send email so can apply logic on it */
    int sendRetryCount;

    @StartSaga
    @SagaEventHandler(associationProperty = "id")
    public void on(UserRegisteredEvent event) {
        id = event.getApplicationId();
        //state = event........
        // what are the possibilities here? 
        // Can we use sendAndWait but it does not scale very well, right?
        commandGateway.send(new SendRegistrationEmailCommand(...));
        // Is deadline good since we do not handle the "send" of the command
    }

    // Use a @DeadlineHandler to retry ?

    @DeadlineHandler(deadlineName = "retry_send_registration_email")
    fun on() {
         // resend command and re-schedule a deadline, etc
    }

    @EndSaga
    @SagaEventHandler(associationProperty = "id")
    public void on(RegistrationEmailSentEvent event) {

    }

}
cqrs saga axon
1个回答
0
投票

理想情况下,您将使用异步选项来处理错误。这可能是commandGateway.send(command)commandGateway.send(command).thenApply()。如果故障与业务逻辑相关,则在这些故障上发出事件可能是有意义的。一个简单的gateway.send(command)才有意义。 Saga可以对由此返回的事件做出反应。否则,您将不得不处理命令的结果。

您是否需要使用sendAndWait还是仅使用send().then...取决于失败时需要执行的活动。不幸的是,当异步处理结果时,您不能再安全地修改Saga的状态。轴突可能已经保留了传奇的状态,导致这些更改丢失了。 sendAndWait解决了这一问题。可伸缩性通常不是问题,因为可以根据处理器配置并行执行不同的Sagas。

[Axon团队目前正在研究可能的API,这些API允许在Sagas中安全地异步执行逻辑,同时仍在保证线程安全性和状态持久性。

© www.soinside.com 2019 - 2024. All rights reserved.