StackSaga Transaction Types
In this section, you will get the architecture of this framework. Other than that, you will get what are the limitations you have to face when you are going to use microservice architecture and how to overcome those difficulties by using StackSAGA framework.
You know that in the saga flow, the transaction can be divided into 3 types according to the behavior of the transaction. Let’s see one by one how the StackSaga’s execution-coordinator coordinates (SEC) each component with each transaction type.
Fully Success Transaction
here, the SEC has successfully executed all the executors. therefore, there is no Compensating/revert execution was invoked. this is the success scenario we wish.
-
1 As the first step the user makes the request and the OrderController catch the request.
-
2 After having the request, initialize the place order aggregator and set the start executor into the StackSaga. (In this time you have the transaction uid which is created by framework. The transaction uid is the unique id for identifying each transaction. You can get it from your created Aggregator object.)
-
3 now the execution processes are handled by the SEC. Before invoking the executor that you provided as the start-executor SEC saves the initial state of the aggregator in the event-tore.
-
4 SEC executes the start-executor ([Command] CreateOrderExecutor) that you provided. 4.1 due to the executing the process method by the SEC, the InternalOrderService’s createOrder() method will be invoked. 4.2 after successfully invoking the method, SEC will store the state of the aggregator. 4.3 after saving the state in the event-store, SEC will execute the onEachProcessPerformed method of the handler class that you provided. 4.4 then you can put your execution here to update the status of the place-order transaction. as the diagram, we have executed updateCustomerOrderStatus() method of InternalOrderService to update the status. 4.5 after updating the status of the place-order, you can notify your customer by sending the email or SMS or whatever method about the status of the order.
-
5 SEC executes the 2nd executor that you provided from the 1st executor. 5.1 due to the executing the doProcess method of the [Query] UserExecutor by the SEC, the ExternalUserStatusService’s checkUser() method will be invoked. 5.2 the ExternalUserStatusService will call the user-service and make a request. 5.3 after successfully invoking the request, SEC will store the state of the aggregator of 2nd process. 5.4 after saving the state in the event-store, SEC will execute the onEachProcessPerformed method of the handler class that you provided.
Due to this executor is a query executor, there is no status update process has been executed here.
-
6 SEC executes the [Command] PaymentExecutor executor that you provided. 6.1 due to the executing the process method by the SEC, the ExternalPaymentService’s makePayment() method will be invoked. 6.2 the ExternalPaymentService will call the payment-service and make a request to make-payment process. 6.3 after successfully making the request, SEC will store the state of the aggregator. 6.4 after saving the state in the event-store, SEC will execute the onEachProcessPerformed method of the handler class that you provided. 6.5 then you can put your execution here to update the status of the place-order transaction. as the diagram, we have executed updateCustomerOrderStatus() method of InternalOrderService to update the status. 6.6 after updating the status of the place-order, you can notify your customer by sending the email or SMS or whatever method about the status of the order.
-
7 SEC executes the [Command] DeliveryExecutor that you provided. 7.1 due to the executing the process method by the SEC, the ExternalDeliveryService’s addToDelivery() method will be invoked. 7.2 the ExternalDeliveryService will call the delivery-service and make a request to add-to-delivery process. 7.3 after successfully making the request, SEC will store the state of the aggregator. 7.4 after saving the state in the event-store, SEC will execute the onEachProcessPerformed method of the handler class that you provided. 7.5 then you can put your execution here to update the status of the place-order transaction. as the diagram, we have executed updateCustomerOrderStatus() method of InternalOrderService to update the status. 7.6 after updating the status of the place-order, you can notify your customer by sending the email or SMS or whatever method about the status of the order.
-
8 as the final step the SEC will invoke the onTransactionCompleted method of the handler. 8.1 you can update the place-order status as the final state as success. 8.2 after updating the place-order status, you can notify it to the customer.
Compensating Success Transaction
here, the SEC hasn’t successfully executed all the executors. an error occurred while after some processing. therefore, the transaction has a Compensating/revert executions.
-
1 as the first step the users make the request and the OrderController catch the request.
-
2 after having the request, initialize the place order aggregator and set the start executor into the StackSaga. (In this time you have the transaction uid which is created by framework. The transaction uid is the unique id for identifying each transaction. You can get it from your created Aggregator object. )
-
3 now the execution processes are handled by the SEC. Before invoking the executor that you provided as the start-executor SEC saves the initial state of the aggregator in the event-tore.
-
4 SEC executes the start-executor ([Command] CreateOrderExecutor) that you provided. 4.1 due to the executing the process method by the SEC, the InternalOrderService’s createOrder() method will be invoked. 4.2 after successfully invoking the method, SEC will store the state of the aggregator. 4.3 after saving the state in the event-store, SEC will execute the onEachProcessPerformed method of the handler class that you provided. 4.4 then you can put your execution here to update the status of the place-order transaction. as the diagram, we have executed updateCustomerOrderStatus() method of InternalOrderService to update the status. 4.5 after updating the status of the place-order, you can notify your customer by sending the email or SMS or whatever method about the status of the order.
-
5 SEC executes the 2nd executor that you provided from the 1st executor. 5.1 due to the executing the doProcess method of the [Query] UserExecutor by the SEC, the ExternalUserStatusService’s checkUser() method will be invoked. 5.2 the ExternalUserStatusService will call the user-service and make a request. 5.3 after successfully invoking the request, SEC will store the state of the aggregator of 2nd process. 5.4 after saving the state in the event-store, SEC will execute the onEachProcessPerformed method of the handler class that you provided.
Due to this executor is a query executor, there is no status update process have been executed here.
-
6 SEC executes the [Command] PaymentExecutor executor that you provided. 6.1 due to the executing the process method by the SEC, the ExternalPaymentService’s makePayment() method will be invoked. 6.2 the ExternalPaymentService will call the payment-service and make a request to make-payment process. at this time, the request failed due to an exception.
-
7 the SEC will invoke onProcessException method of the handler class that you provided. there you can get notified about the process failure. the transaction can’t be executed forward anymore, the Compensating process will start from this point.
**if you want to update the order status or update the customer, you can invoke your code here. in this example, it hasn’t been implemented.
-
8 due to the final successful executed OrderExecutor (There is no Compensating because the UserExecutor is a query executor.) SEC invokes the doRevert method of the OrderExecutor. 8.1 due to the executing of the doRevert method, createOrderRevert method will be invoked and do the revert process of the make-payment. 8.2 in the Compensating process if you want to store some data regarding the revert process, you can store them into the [hint-store] the framework provides. that stored data is saved at this step. 8.4 after invoking successfully the revert, the SEC will invoke onEachRevertPerformed method regarding the revert process. 8.4 the customer will be notified about the revert process. (if you want to update the order status, you can invoke your code here as well. that part hasn’t been implemented in this example.)
-
9 StackSaga state-machine knows that the Compensating is done. therefore, SEC invokes the onTransactionCompleted method as REVERT_SUCCESS. 9.1 you can update the status of the place-order regarding the revert was processed. 9.2 after that the customer will be notified about the revert success process of their order.
To keep the overall state of the transaction eventually consistent, the revert processes (Compensating processes) can be retryable. Because all the Compensatings must be invoked. To have knowledge about how retry works of revert-processes in StackSaga, please refer to this. |
Compensating Failed Transaction
Even though if there is a Compensating Failed Transaction for theoretically, Make sure that a revert exception doesn’t occur in your production application. |
Can we ignore the Exceptions to execute the rest of revert executions? The answer is yes. You know that if an exception happens while reverting the entire transaction, the transaction is terminated from that point. Then the next rest of revert executions that should be invoked are not executed. Sometimes that can have some revert-executions more important to be executed, and it is a must. But if you have an error before executing that revert-execution, that important revert-execution is not executed. Most of the time, those exceptions will be that you didn’t except. To avoid transaction-termination due to revert-error, you can catch all the exceptions and filter the exception that you know well and ignore another all rest of exceptions without throwing to the SEC. [ See a real usage ] |