让我们举一个电子邮件传奇的例子:当一个用户注册时,我们创建一个发布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将监听它(并最终注册一个最后期限以防万一);接收者也可以发送事件以通知错误和不投掷,佐贺也将监听此事件。
理想情况下,您将使用异步选项来处理错误。它可以是commandgateway.send(命令)
或commandgateway.send(命令).thenapply()
。如果故障与businesslogic相关,那么对这些故障发出事件可能是有意义的。一个普通的gateway.send(command)
是有意义的;传奇可以对结果返回的事件做出反应。否则,您将不得不处理命令的结果。
您是需要使用sendandwait
还是仅仅使用send()。然后…
取决于失败时需要执行的活动。不幸的是,在异步处理结果时,您不能再安全地修改Saga的状态。Axon可能已经保持了传奇的状态,导致这些变化消失了。sendandwait
可以解决这个问题。可伸缩性通常不是一个问题,因为不同的SAGA可以并行执行,这取决于您的处理器配置。
Axon团队目前正在研究可能的API,这些API将允许安全异步执行Sagas中的逻辑,同时仍然保证线程安全和状态持久性。
中的任何提示都非常感谢,谢谢。
exception$10(errorcode.java:88)在org.axonframework.axonserver.connector.errorcode.convert(errorcode.java:182)在org.axonframework.axonserver.connector.command.command.command.axonservercommandbus$1.onnex
因此,目前我正在用axon框架实现一个saga,使用事件源和CQRS。 情况如下: 我有3个微服务,m1、m2和m3 用户在GUI中输入由m1、m2、m3分别处理和保存的3个实体e1、e2、e3的数据,因此M1->e1、M2->e2、M3->e3 现在来看看这个传奇的必要性: e1没有e2就不能存在,e2没有E3就不能存在。 因此,所有3个实体必须由它们各自的服务成功创建,如果其中一个失败,则sa
您可以在下面看到我的示例类。 基本上,我希望使用Axon的表来存储事件,并使用我自己的实体表来存储实体。我知道,如果我激发在聚合中处理的,将发布一个事件,之后它将转到,Axon将在其表中持久化该事件。 如何回滚表,还是应该为此使用补偿事件? 我的外部@EventHandler类:
任何关于如何做到这一点的文件都将不胜感激。 提前谢了。
null 我想要达到的目标 我希望由一个实例发布的事件只由同一个实例处理 如果instance1发布eventX,那么只有instance1应该处理eventX null