Saga Executors.

According to the saga design pattern, sub processes (atomic executions) can have two executions called process execution and Compensating execution. And those executions you van create as the methods in your application anywhere.

  1. Query executors: If some atomic process has no Compensating, that kind of process is used in a query executor.

  2. Command executors: If some atomic process has a Compensating (revert execution), that kind of process is used in a command executor.
    Revert executors: For the Compensating process of the command executor it can be used other sub processes if you need.

    1. Revert Before Executors: If you want to execute an atomic process before executing the main revert process, you can create a Revert-Before-Executor.

    2. Revert After Executors: If you want to execute an atomic process after executing the main revert process, you can create a Revert-Before-Executor.

Query Executor.

You can create any number of your custom Query-Executors regarding the Aggregator. Here you can see how you can create a Query-Executor for your PlaceOrderAggregator.

(1)
@SagaExecutor(
        executeFor = "user-service", (2)
        liveCheck = true, (3)
        value = "CheckUserExecutor" (4)
)
public class CheckUserExecutor implements QueryExecutor<PlaceOrderAggregator> { (5)

    (6)
    @Override
    public ProcessStepManager<PlaceOrderAggregator> doProcess(
            ProcessStack processStack,
            PlaceOrderAggregator aggregator,
            ProcessStepManagerUtil<PlaceOrderAggregator> stepManagerUtil
    ) throws RetryableExecutorException, NonRetryableExecutorException {
        //execute the service and check the conndtion.

        //return or throw (7)
    }
}
1 @SagaExecutor: annotate your query executor with @org.stacksaga.annotation.SagaExecutor annotation. The annotation provides the spring bean capabilities and also another metadata for the StackSaga framework.
2 executeFor: The name of the service that particular executor is going to be connected. it can be a service name of another service. if the service is spring boot service, make sure to keep the application name as its. because it will be helpful for the retry process.
3 liveCheck: When the retry process is executed, liveCheck is considered by the engine. if the target service is a spring boot service or registered service with the service registry, the availability is checked before executing the retry by the StackSaga engine.
4 value: The bean name of the executor. The executor is identified with this value by StackSaga engine. after configuring the bean name, it cannot be changed at all. if you want to the class package, it does not matter without changing the configured name.
5 QueryExecutor<T> IF the executor is Query one, The executor should be implemented by org.stacksaga.executor.QueryExecutor<T>. T should be the target Aggregator class for the domain.
6 Override the doProcess() method and put your execution code block that should be executed when the executor is executed by the StackSaga engine.
7 Finally, you can either return the next executor with the method that provides by the ProcessStepManager.

Command Executor.

(1)
@SagaExecutor(
        executeFor = "delivery-service", (2)
        liveCheck = true, (3)
        value = "DispatchOrderExecutor" (4)
)
public class DispatchOrderExecutor implements CommandExecutor<PlaceOrderAggregator> { (5)

    (6)
    @Override
    public ProcessStepManager<PlaceOrderAggregator> doProcess(
            ProcessStack processStack, (7)
            PlaceOrderAggregator aggregator, (8)
            ProcessStepManagerUtil<PlaceOrderAggregator> stepManager (9)
    ) throws RetryableExecutorException, NonRetryableExecutorException {
        //execute the service and check the conndtion.
        ...
        //return or throw (10)
    }

    @RevertBefore(startFrom = DispatchRevertNotifierExecutor.class) (11)
    @RevertAfter(startFrom = DispatchRevertCompleteLogExecutor.class) (12)
    @Override
    public void doRevert(
            ProcessStack processStack,(13)
            NonRetryableExecutorException nonRetryableExecutorException,(14)
            PlaceOrderAggregator aggregator, (15)
            RevertHintStore revertHintStore (16)
    ) throws RetryableExecutorException {
        //call the atomic process that you want to as the Compensating,
        ...
    }
}
1 @SagaExecutor: annotate your query executor with @org.stacksaga.annotation.SagaExecutor annotation. The annotation provides the spring bean capabilities and also another metadata for the StackSaga framework.
2 executeFor: The name of the service that particular executor is going to be connected. it can be a service name of another service. if the service is spring boot service, make sure to keep the application name as its. because it will be helpful for the retry process.
3 liveCheck: When the retry process is executed, liveCheck is considered by the engine. if the target service is a spring boot service or registered service with the service registry, the availability is checked before executing the retry by the StackSaga engine.
4 value: The bean name of the executor. The executor is identified with this value by StackSaga engine. after configuring the bean name, it cannot be changed at all. if you want to the class package, it does not matter without changing the configured name.
5 CommandExecutor<T> IF the executor is command one, The executor should be implemented by org.stacksaga.executor.CommandExecutor<T>. T should be the target Aggregator class for the domain.
6 Override the doProcess() method and put your execution code block that should be executed when the executor is executed by the StackSaga engine.
7 ProcessStack Object provides all the executed execution until the process so far. It will help for gen an idea about the execution history. And also you can get the decision of the execution base on the execution history.
8 PlaceOrderAggregator: The current aggregator state.
9 ProcessStepManagerUtil<T>: This object provides the methods for giving the navigation to the engine regarding the next step. it can be another executor (command or query) or a process completion.
10 Inside the method scope, you can provide the execution that should be executed when the StackSaga engine executes. And finally you can navigate to the next step by using the ProcessStepManagerUtil object.
11 @RevertBefore: If the executor has any revert-before-executors, you can mention that executor class with @RevertBefore annotation. According to the example, the revert before execution will be started from DispatchRevertNotifierExecutor.
12 @RevertAfter: If the executor has any revert-after-executors, you can mention that executor class with @RevertAfter annotation. According to the example, the revert after execution will be started from DispatchRevertCompleteLogExecutor.
13 ProcessStack The final process stack that was when the final execution was executed.
14 NonRetryableExecutorException The exception that caused the transition process stopping to forward.
15 PlaceOrderAggregator The final aggregator state when the NonRetryableExecutorException is thrown.
16 RevertHintStore If you want to add some data to the backward process, you can use the RevertHintStore to put the data.

Revert Before Executor.

(1)
@SagaExecutor(
        executeFor = "delivery-service",(2)
        liveCheck = true,(3)
        value = "DispatchRevertNotifierExecutor" (4)
)
public class DispatchRevertNotifierExecutor implements RevertBeforeExecutor<PlaceOrderAggregator, DispatchOrderExecutor> {(5)

    (6)
    @Override
    public RevertBeforeStepManager<PlaceOrderAggregator, DispatchOrderExecutor> doProcess(
            PlaceOrderAggregator aggregator,(7)
            ProcessStack previousProcessStack,(8)
            NonRetryableExecutorException processException,(9)
            RevertHintStore revertHintStore,(10)
            RevertBeforeStepManagerUtil<PlaceOrderAggregator, DispatchOrderExecutor> revertStepManagerUtil (11)
    ) throws RetryableExecutorException { (12)
        return revertStepManagerUtil.next(NextBeforExecutor.class); (13)
        //or
        return revertStepManagerUtil.complete(); (14)
    }
}
1 @SagaExecutor: annotate your query executor with @org.stacksaga.annotation.SagaExecutor annotation. The annotation provides the spring bean capabilities and also another metadata for the StackSaga framework.
2 executeFor: The name of the service that particular executor is going to be connected. it can be a service name of another service. if the service is spring boot service, make sure to keep the application name as its. because it will be helpful for the retry process.
3 liveCheck: When the retry process is executed, liveCheck is considered by the engine. if the target service is a spring boot service or registered service with the service registry, the availability is checked before executing the retry by the StackSaga engine.
4 value: The bean name of the executor. The executor is identified with this value by StackSaga engine. after configuring the bean name, it cannot be changed at all. if you want to the class package, it does not matter without changing the configured name.
5 RevertBeforeExecutor<A, E>: The Revert Before Executor should be implemented from the RevertBeforeExecutor<A,E>. Generic A is the aggregator. Generic E is the command-executor of the given aggregator as the Generic A.
6 Override the doProcess() method that RevertBeforeExecutor provides. That is the method is executed by the StackSaga engine.
7 PlaceOrderAggregator: The final aggregator state when the process exception is thrown.
8 ProcessStack: The final process stack when the process exception is thrown.
9 NonRetryableExecutorException:The process-exception that was thrown by the last executor.
10 RevertHintStore If you want to add some data to the backward process, you can use the RevertHintStore to put the data as container.
11 RevertBeforeStepManagerUtil<A, E>: This object provides the methods for giving the navigation to the engine regarding the next step. it can be another revert-before-executor or a revert-before completion.
12 RetryableExecutorException: If the revert before execution is failed due to a retryable exception, you can provide that by warping with RetryableExecutorException.
13 next(): You can provide (only if you have) the next revert-before-executor with revertStepManagerUtil.next().
14 complete(): If you don’t have any revert-before-executor to be executed as next regarding the command-executor, you can return revertStepManagerUtil.complete().

Revert After Executor.

(1)
@SagaExecutor(
        executeFor = "delivery-service",(2)
        liveCheck = true,(3)
        value = "DispatchRevertNotifierExecutor" (4)
)
public class DispatchRevertCompleteLogExecutor implements RevertAfterExecutor<PlaceOrderAggregator, DispatchOrderExecutor> {(5)

    (6)
    @Override
    public RevertAfterStepManager<PlaceOrderAggregator, DispatchOrderExecutor> doProcess(
            PlaceOrderAggregator aggregator,(7)
            ProcessStack previousProcessStack,(8)
            NonRetryableExecutorException processException,(9)
            RevertHintStore revertHintStore,(10)
            RevertAfterStepManagerUtil<PlaceOrderAggregator, DispatchOrderExecutor> revertStepManagerUtil (11)
    ) throws RetryableExecutorException { (12)
        return revertStepManagerUtil.next(NextAfterExecutor.class); (13)
        //or
        return revertStepManagerUtil.complete(); (14)
    }
}
1 @SagaExecutor: annotate your query executor with @org.stacksaga.annotation.SagaExecutor annotation. The annotation provides the spring bean capabilities and also another metadata for the StackSaga framework.
2 executeFor: The name of the service that particular executor is going to be connected. it can be a service name of another service. if the service is spring boot service, make sure to keep the application name as its. because it will be helpful for the retry process.
3 liveCheck: When the retry process is executed, liveCheck is considered by the engine. if the target service is a spring boot service or registered service with the service registry, the availability is checked before executing the retry by the StackSaga engine.
4 value: The bean name of the executor. The executor is identified with this value by StackSaga engine. after configuring the bean name, it cannot be changed at all. if you want to the class package, it does not matter without changing the configured name.
5 RevertAfterExecutor<A, E>: The Revert After Executor should be implemented from the RevertAfterExecutor<A,E>. Generic A is the aggregator. Generic E is the command-executor of the given aggregator as the Generic A.
6 Override the doProcess() method that RevertAfterExecutor provides. That is the method is executed by the StackSaga engine.
7 PlaceOrderAggregator: The final aggregator state when the process exception is thrown.
8 ProcessStack: The final process stack when the process exception is thrown.
9 NonRetryableExecutorException:The process-exception that was thrown by the last executor.
10 RevertHintStore If you want to add some data to the backward process, you can use the RevertHintStore to put the data as container.
11 RevertAfterStepManagerUtil<A, E>: This object provides the methods for giving the navigation to the engine regarding the next step. it can be another revert-after-executor or a revert-after completion.
12 RetryableExecutorException: If the revert after execution is failed due to a retryable exception, you can provide that by warping with RetryableExecutorException.
13 next(): You can provide (only if you have) the next revert-after-executor with revertStepManagerUtil.next().
14 complete(): If you don’t have any revert-after-executor to be executed as next regarding the command-executor, you can return revertStepManagerUtil.complete().