当前位置: 首页 > 知识库问答 >
问题:

如何在axon框架中处理从saga发送的命令

景唯
2023-03-14

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

我们是否应该使用:

>

  • commandgateway.sendandwait用try/catch->缩放吗?

    使用deadline是因为我们只使用“send”,而不处理命令的最终错误,这可能是发送失败(其他服务关闭,等等)

    其它的呢?

    还是所有的结合?

    我错过的其他错误?

    @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) {
    
        }
    
    }
    

    编辑(在接受答案后):

    主要有两个选项(抱歉,下面是科特林代码):

    commandGateway.send(SendRegistrationEmailCommand(...))
        .handle({ t, result ->
        if (t != null) {
           // send event (could be caught be the same saga eventually) or send command or both
        }else{
           // send event (could be caught be the same saga eventually) or send command or both
        }
        })
    // If not use handle(...) then you can use thenApply as well
        .thenApply { eventGateway.publish(SomeSuccessfulEvent(...)) }
        .thenApply { commandGateway.send(SomeSuccessfulSendOnSuccessCommand) }
    

    似乎最好只在命令发送失败或接收者抛出意外异常时才使用handle(),如果是这样,则发布一个事件让saga对其进行操作。在成功的情况下,接收者应该发布事件,saga将监听它(并最终注册一个最后期限以防万一);接收者也可以发送事件以通知错误和不投掷,佐贺也将监听此事件。

  • 共有1个答案

    壤驷喜
    2023-03-14

    理想情况下,您将使用异步选项来处理错误。它可以是commandgateway.send(命令)commandgateway.send(命令).thenapply()。如果故障与businesslogic相关,那么对这些故障发出事件可能是有意义的。一个普通的gateway.send(command)是有意义的;传奇可以对结果返回的事件做出反应。否则,您将不得不处理命令的结果。

    您是需要使用sendandwait还是仅仅使用send()。然后…取决于失败时需要执行的活动。不幸的是,在异步处理结果时,您不能再安全地修改Saga的状态。Axon可能已经保持了传奇的状态,导致这些变化消失了。sendandwait可以解决这个问题。可伸缩性通常不是一个问题,因为不同的SAGA可以并行执行,这取决于您的处理器配置

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

     类似资料: