SagaTemplates
Saga Template is the bridge between your application and the StackSaga engine. It is the entry point for starting a transaction process and hand off the control to the StackSaga engine.
There are two types of SagaTemplates in StackSaga.
-
SagaTemplate<A>: It is used for synchronous/blocking transaction processing. (For web MVC applications) -
ReactiveSagaTemplate<A>: It is used for asynchronous/non-blocking transaction processing. (For webflux applications)
SagaTemplate<A>
@RestController
@RequestMapping("/order")
@AllArgsConstructor
public class PlaceOrderSagaController {
private final SagaTemplate<PlaceOrderAggregator> sagaTemplate; (1)
@PostMapping
@ResponseStatus(HttpStatus.ACCEPTED)
public Map<String, String> placeOrder() {
(2)
PlaceOrderAggregator aggregator = new PlaceOrderAggregator();
aggregator.setUsername("mafei");
aggregator.setTotal(200.00);
(3)
this.sagaTemplate.process(
aggregator,
CheckUserExecutor.class
);
(4)
return Collections.singletonMap(
"order_id",
aggregator.getAggregatorTransactionId()
);
}
}
| 1 | Autowire(inject) the SagaTemplate by providing the target Aggregator Class. |
| 2 | Initialize your aggregator by providing the initial data. |
| 3 | Use the autowired SagaTemplate object and call the process(..) method.
As the first argument, you have to provide the initialized target aggregator object.
As the second argument you have to provide, which is the first executor that should be started the transaction.
According to the example, The 1st executor is CheckUserExecutor.class.
It can be either Command-Executor or Query-Executor. |
| 4 | Returns the response by obtaining the aggregatorTransactionId from the initialized object. |
Due to the fact that the target aggregator class has been extended from the Aggregator, you can use inherited methods from Aggregator class.
The getAggregatorTransactionId() method is one of inherited methods from Aggregator class.
It will provide you the unique ID for each object (each transaction) that you initialize.
It will be the transaction id for the entire transaction.
|
ReactiveSagaTemplate<A>
@RestController
@RequestMapping("/order")
@AllArgsConstructor
public class PlaceOrderSagaController {
private final ReactiveSagaTemplate<PlaceOrderAggregator> reactiveSagaTemplate; (1)
@PostMapping
@ResponseStatus(HttpStatus.ACCEPTED)
public Mono<Map<String, String>> placeOrder() {
(2)
(2)
PlaceOrderAggregator aggregator = new PlaceOrderAggregator();
aggregator.setUsername("mafei");
aggregator.setTotal(200.00);
(3)
return this.reactiveSagaTemplate
.process(placeOrderAggregator, ReactiveCheckUserExecutor.class)
.map(transactionId -> Collections.singletonMap("order_id",transactionId));
}
}
| 1 | Autowire(inject) the ReactiveSagaTemplate by providing the target aggregator Class. |
| 2 | Initialize your aggregator by providing the initial data. |
| 3 | Use the autowired ReactiveSagaTemplate object and call the process(..) method.
As the first argument, you have to provide the initialized target aggregator object.
As the second argument you have to provide, which is the first executor that should be started the transaction.
According to the example, The 1st executor is ReactiveCheckUserExecutor.class.
It can be either Command-Executor or Query-Executor.
The process(..) method will return a Mono<String> which contains the transaction id.
You can use that transaction id to return the response. |
Customizing the SagaTemplate’s Execution Scheduler
Even SagaTemplate seems like blocking one, it internally operates in reactive, non-blocking manner.
So transaction processing is offloaded to a dedicated reactive scheduler to be executed asynchronously, By default boundedElastic is used, If customization is required, you can override the default scheduler by providing a custom Scheduler bean named beanNonReactiveTxExecutorScheduler (use the static identifier Stacksaga.BEAN_NON_REACTIVE_TX_EXECUTOR_SCHEDULER).
@Bean(Stacksaga.BEAN_NON_REACTIVE_TX_EXECUTOR_SCHEDULER)
//@Bean("beanNonReactiveTxExecutorScheduler")
public Scheduler scheduler() {
return Schedulers.newBoundedElastic(10, 100, "non-reactive-tx-executor-pool");
}