Requirements:
- BPMN activities:
- service task activity
- fork and split gateway for a parallel execution of activities
- compensation activity
- compensation logics
- automatic trigger of compensation on exception
- reverse order on compensation
- store, read, and pass variables
- save point after each activity for fault tolerance (e.g., DB or file system)
- visualization of transactions for debugging and manual compensation purposes
Scenario:
- create pending order
- reduce inventory
- fulfil payment
- publish order
Start a saga instance:
// start saga instance from saga model "order creation"
orderCreationSaga = sagaFactory.startNewInstanceFromSagaModel("order creation")
orderId = orderCreationSaga.getVariables().getOrWait("orderId", 500, Millis)
orderCreationSaga.waitForCompletion(3_000, Millis)
The task to execute a single saga step:
public SagaStepRunnable(SagaInstance sagaInstance, SagaActivity sagaActivity) {
this.sagaInstance = sagaInstance;
this.sagaActivity = sagaActivity;
}
@Override
public void run() {
SagaLog sagaLog = sagaInstance.getSagaLog();
try {
sagaActivity.execute(sagaInstance.getVariables());
// if the thread crashes at this point, the saga restarts after the last successful activity.
// hence, all activities (local and remote) must be idempotent.
sagaLog.storeSuccessEventFor(sagaActivity, sagaInstance.getVariables());
} catch (Exception e) {
sagaLog.storeFailureEventFor(sagaActivity, sagaInstance.getVariables(), e);
sagaInstance.switchToCompensationMode();
}
sagaInstance.scheduleNextActivities();
}
Questions:
- necessary to sync “entity creation for order” with “current variables” and “success event”?
- remote AND local services must be idempotent?