简体   繁体   中英

Axon how can I catch exception in saga

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM