In this post we are going to explain how can we orchestrate microservices with our BPM Engine based in Camunda.
First of all, lets introduce what Saga Pattern is and how it works.
Saga is one of the most well-known patterns for distributed transactions.
A saga is a sequence of local transactions where each transaction updates data within a single service. The first transaction is initiated by an external request corresponding to the system operation, and then each subsequent step is triggered by the completion of the previous one.
There are two different approaches to accomplish the Saga pattern:
Events/Choreography: When there is no central coordination, each service produces and listen to other service’s events and decides if an action should be taken or not.
Command/Orchestration: when a coordinator service is responsible for centralizing the saga’s decision making and sequencing business logic.
In this post we will take care of the second approach, as it is the most scalable, simple to understand, and consistent one.
BPM Engine as orchestrator
Camunda BPM Engine provides the tools to orchestrate services following the Saga pattern. With compensation events attached to each transaction (task), the engine can listen to them in a centralized way and take compesation measures for rollback.
Here’s an example:
You can notice that for each transaction task, a compensation action is defined through a compensation boundary event.
Furthermore, compensation actions are taken in cascade, this means that if “book hotel” fails, then “cancel car” is executed. If “book flight” fails, then “cancel hotel” and “cancel car” actions are executed.
So, how are failures/erros handled in Camunda?
The magic resides in the subflow underneath. This subflow will be triggered when any error is thrown wihtin the transaction tasks. When started, a compensation event will be thrown, and compensation actions taken.
In this example, the first two tasks are mocked, they only log in console a message. On the other hand, the last one makes an http call, and if the http status code is different than 200, then a generic exception is thrown with error code “error-http-response”.
In the subflow, the compensation start event is listening to any error of this type:
If we start this business process, you can see in the console the logs for the tasks that are being executed: