Sample Java Application demonstrating Saga microservice architecture pattern for a cab booking app.
See: https://medium.com/orkes/saga-pattern-in-distributed-systems-f11b9a2221f5 for the blog
- Install JAVA 17 - https://www.oracle.com/java/technologies/javase/jdk17-archive-downloads.html
- Install sqlite - https://www.tutorialspoint.com/sqlite/sqlite_installation.htm.
If using brew, you can just run
brew install sqlite
We have already setup these workflows with all the necessary permissions. These can be used directly, if you don't need to modify these workflows.
- Booking workflow - https://play.orkes.io/workflowDef/cab_service_saga_booking_wf
- Cancellation workflow - https://play.orkes.io/workflowDef/cab_service_saga_cancellation_wf
Using the below workflow definitions, you can create a copy of these workflows and customize as per your need. You will have to rename both the workflows to avoid conflicts with the out-of-the-box workflows.
- Create booking workflow by uploading workflow definition - cab_service_saga_booking_wf.json
- Create cancellation workflow by uploading workflow definition - cab_service_saga_cancellation_wf.json
- Clone the project to your local
- Update following properties in application.properties
conductor.security.client.key-id
andconductor.security.client.secret
are NOT set, please set them- When connecting to playground - refer to this article to get a key and secret
- When connecting locally - follow the instructions here (Install and Run Locally)
conductor.worker.all.domain
is set to 'saga' by default, please change it to or something else to avoid conflicts with workflows and workers spun up by others
- From the root project folder, run
mvn spring-boot:run
We can use two approaches:
- Call the triggerRideBookingFlow API from within the Application
curl --location 'http://localhost:8081/triggerRideBookingFlow' \ --header 'Content-Type: application/json' \ --data '{ "pickUpLocation": "150 East 52nd Street, New York, NY 10045", "dropOffLocation": "120 West 81st Street, New York, NY 10012", "riderId": 1 }'
- Directly call the Orkes API for creating a workflow
- Generate a JWT token by following steps mentioned here
- Make an HTTPS request from postman/curl similar to below after replacing <JWT Token>:
curl --location 'https://play.orkes.io/api/workflow' \ --header "Content-Type: application/json" \ --header 'X-Authorization: <JWT Token>' \ --request POST \ --data '{ "name": "cab_service_saga_booking_wf", "version": 1, "input": { "pickUpLocation": "250 East 52nd Street, New York, NY 10045", "dropOffLocation": "120 West 81st Street, New York, NY 10012", "riderId": 1 }, "taskToDomain": { "*": "saga" } }'
A successful booking creation workflow run will look like this:
- Create a booking for rider 3 who doesn't have a payment method seeded.
curl --location 'https://play.orkes.io/api/workflow' \
--header "Content-Type: application/json" \
--header 'X-Authorization: <JWT Token>' \
--request POST \
--data '{
"name": "cab_service_saga_booking_wf",
"version": 1,
"input": {
"pickUpLocation": "250 East 52nd Street, New York, NY 10045",
"dropOffLocation": "120 West 81st Street, New York, NY 10012",
"riderId": 3
},
"taskToDomain": {
"*": "saga"
}
}'
-
This will cause the workflow to fail and trigger the cancellation workflow.
-
Failed booking workflow run will look like this:
-
A cancellation workflow run will look like this:
-
In the above workflow diagram, the simulated distributed rollback can be seen. The rollback sequence in case of failure occurring while payment processing is as follows:
- Payment is cancelled in the Payment Service
- Driver assignment is deactivated the Cab Assignment Service
- Booking is cancelled and driver association is removed in the Booking Service