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.
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.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.