Domo42/saga-lib

onHandlerExecutionError method for SagaLifetimeInterceptor

huetti79 opened this issue · 2 comments

Consider you have more than one saga handling a specific message and in the first saga an exception occurs in the event handler. This exception will stop the whole SagaExecutionChain and the subsequent event handler of other sagas will never be executed.

In the SagaModules you can react on exceptions though, but these handlers are called outside the saga execution chain. Which means in case of an exception in a saga event handler you only get the execution context of this failed saga and no information about the subsequent sagas.

If the SagaInterceptor interface provides also an onError method like SagaModule has, the exception can be handled individually for the current saga (e.g. closing resources like DB sessions; automatically rollback active transactions, ... ) and still decide with the ExecutionContext wether to continue or stop the current execution chain for this message.

My suggestion would be to add a method similiar to this to the SagaLiftetimeIntereceptor interface and to adopt the SagaExecutionTask accordingly.
/** * This method is called in case an exception during execution of a handler occurs. This * includes the start handler as well as all other handlers called as long * as the saga is not finished. */ default void onHandlerError(Saga<?> saga, ExecutionContext context, Object message, Throwable t) {}

@Domo42 shall I provide a PR

Sorry about the late answer.

What is the more concrete use case for this feature?

You mention closing DB sessions and transaction rollbacks. This is expected to be done in a module. Same as starting a transaction, as it "usually" encompasses the the complete logic associated with a message.

If a transaction is started within a single saga handler isn't it more consistent that this transaction starts and closes it within the very same handler?

Checking the pull request, it also does not solve the last part you mention, which is an optional continuation of the handling regardless of errors. The exception is re-thrown stopping the execution of other handlers in the very same way.

As you describe it, the problem looks as if a single event needs different handling and/or compensation without any logical or transactional correlation. In such a case, I'd recommend to handle the originating event in its own single handler, creating a number of sub-events with their own execution chain and transaction context.