英文:
Axon how can I catch exception in saga
问题
假设我想创建一个简单的请求-批准系统,如果用户向另一个用户发出请求,它应该创建该请求,因此我有两个聚合**用户,请求**。请求创建后,它将触发**RequestSaga**以发送**RequestUserCmd**
//聚合类
@Aggregate
class RequestAggregate {
@AggregateIdentifier
private lateinit var requestId: String
@CommandHandler
constructor(cmd: CreateRequestCmd){
apply(RequestCreatedEvt(
...一些参数
))
}
}
@Aggregate
class UserAggregate {
@TargetAggregateIdentifier
private lateinit var userId: String
private var available = false
// 其他一些命令
@CommandHandler
constructor(cmd: RequestUserCmd){
if(!available) throw IllegalArgumentException("用户不可用。")
apply(UserRequestedEvt(
...一些参数
))
}
}
//Saga类
@Saga
class RequestSaga {
@Autowired
@Transient
private lateinit var commandGateway: CommandGateway
@StartSaga
@SagaEventHandler(associationProperty = "requestId")
fun on(evt: RequestCreatedEvt){
commandGateway.sendAndWait<String>(RequestUserCmd(
...一些参数
))
}
}
我期望的是,如果用户此时不可用,它应该引发异常,而请求不应该被创建。
@RestController
class RequestController {
// 其他代码...
@PostMapping
fun request(@RequestBody request: Request){
// 如果用户不可用,我希望返回 403 错误请求
commandGateway.send<String>(CreateRequestCmd(
...一些参数
))
}
}
但实际上,在用户此时不可用的情况下,请求仍然成功被创建。我应该如何解决这个问题。
英文:
Suppose I want to create a simple request-approve system, If the user requests for something to another user it should create the request so I have two aggregates User, Request. After the request has been created it will trigger RequestSaga to send RequestUserCmd
//Aggregate class
@Aggregate
class RequestAggregate {
@AggregateIdentifier
private lateinit var requestId: String
@CommandHandler
constructor(cmd: CreateRequestCmd){
apply(RequestCreatedEvt(
...some arguments
))
}
}
@Aggregate
class UserAggregate {
@TargetAggregateIdentifier
private lateinit var userId: String
private var available = false
// Some other commands
@CommandHandler
constructor(cmd: RequestUserCmd){
if(!available) throw IllegalArgumentException("User is not available.")
apply(UserRequestedEvt(
...some arguments
))
}
}
//Saga class
@Saga
class RequestSaga {
@Autowired
@Transient
private lateinit var commandGateway: CommandGateway
@StartSaga
@SagaEventHandler(associationProperty = "requestId")
fun on(evt: RequestCreatedEvt){
commandGateway.sendAndWait<String>(RequestUserCmd(
...some arguments
))
}
}
what I expected is, if the user is not available at that time it should raise exception and the request should not been created.
@RestController
class RequestController {
// something...
@PostMapping
fun request(@RequestBody request: Request){
// if the use is not available i want it to return 403 bad request instead
commandGateway.send<String>(CreateRequestCmd(
...some arguments
))
}
}
but in reality, the request has been created successfully even the user is not available at that time how do I manage to solve this case.
答案1
得分: 1
RequestSaga
(或任何一种Saga实现)应意识到它发送的操作可能会失败。它是您的“复杂业务交易”的核心,其中也包括错误情况。
因此,您应该意识到从RequestSaga
发送的RequestUserCmd
可能会失败。由于您正在使用CommandGateway#sendAndWait(Object)
方法,这意味着命令处理函数抛出的异常将可以在Saga中捕获。因此,在sendAndWait
周围放置一个简单的try-catch块就可以了。
如何应对异常完全取决于您的领域。也许您会重试该操作?或者您可以安排一个截止时间在5分钟后重试该操作?还是5天后?或者您可以发送另一个命令回到请求服务,说明用户不可用?
对于这个问题,没有“一刀切”的解决方案,因为只有您的领域专家才能告诉您如果这样的操作失败,您应该做什么。
无论如何,希望这对您有所帮助,@Patrick。如果我的回答不清楚,请添加一些评论,我会看看如何更新我的答案以满足您的需求。
英文:
The RequestSaga
(or any Saga implementation for that matter) should be aware that operations it sends might fail. It is the heart of your "complex business transaction", which also includes faulty scenarios.
Thus, you should be aware that the RequestUserCmd
you send from the RequestSaga
can fail. As you are using the CommandGateway#sendAndWait(Object)
method, that means the exception thrown by the command handling function will be catchable in the Saga. Thus a simple try-catch block around the sendAndWait
will do.
How your react on the exception is however entirely up to your domain. Maybe you retry the operation? Or maybe you schedule a deadline to retry the operation in 5 minutes? Of in 5 days? Or maybe you can send another command back to the request service stating the user is unavailable?
There is no "one size fits all" solution to that question, as only your domain expert can tell you what you should be doing if such an operation fails.
Regardless, I hope this helps you out @Patrick. Please add some comments if my response is unclear to you and I'll see how to update my answer to tailor those needs.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论