SAGA Implementation in C#

March 13 2023


Many thanks to the sponsors who make it possible for this newsletter to be free for readers.



Today's issue is sponsored by Packt



Working with React doesn't have to be complex. "React 18 Design Patterns and Best Practices" empowers you to harness React's potential, making your applications flexible, easy to manage, and high-performing. Discover and unravel the dynamic features of React 18 and Node 19. This updated fourth edition equips you with insights into the cutting-edge tools that will elevate your projects. Book Link.




The background



The SAGA pattern is used to manage transactions across multiple services in a distributed system. It ensures that all services involved in a transaction are coordinated and that the transaction can be rolled back if any of the services fail.

In my example, I will create an Hotel microservice that will initiate the transaction, and a Flight microservice that will complete the transaction.

I will use MassTransit Automatonymous (there are many libraries for working with sagas, even lightweight ones), which is a state machine library for building distributed systems. It provides a way to define the behavior of a system as a state machine, and it handles the coordination between services using the SAGA pattern.

To implement SAGA in C# you need to follow next 5 steps.
Full Demo project is on GitHub repo.


Step 1#: Configure RabbitMQ



First, you need to install the RabbitMQ on your machine. You can do it through Docker container with a following command:

RabbitMQ Installation on Docker

Then, you need to install the RabbitMQ client library in your solution. You can use the NuGet Package Manager to install the RabbitMQ Client package. Then, you need to configure the queues in the appsettings.json file (In GitHub project repo, this is already configured).

Here is an example:

RabbitMQ Configuration in appsettings.json



Step 2#: Automatonymous State Machine



Next, you need to define the state machine using Automatonymous. You can create a class that inherits from the AutomatonymousStateMachine base class and defines the states and transitions.

Here is an example:

Booking State Machine Saga Pattern

This state machine defines 4 states:

- HotelBookingReceived
- HotelBooked
- FlightReservationReceived
- FlightReserved

and 3 events:

- BookHotelCommand
- HotelBookedEvent
- ReserveFlightCommand

It also defines certain transitions from one state to another, as well as event calls in certain states.


Step 3#: Create the Consumers



Next, you need to create the consumers for the events sent by the Hotel and Flight microservices. You can create a class that implements the IConsumer interface and handles the events. There is a 3 consumers.

Here is an example for ReserveFlightConsumer:

Reserve Flight Consumer



Step 4#: Configure MassTransit bus



In this step, you need to configure the MassTransit bus to handle the events and start the consumers. You can use the MassTransit extensions for .NET to configure the bus in the ConfigureServices method of the Startup class.

Here is the configuration in my project:

Mass Transit Bus Configuration

This configuration registers the state machine and the consumers with the MassTransit bus, and sets up the RabbitMQ host and queues. You use the AddScoped method to register the OrderStateMachine as a scoped dependency, so that it can be used by the consumers.


Step 5#: Publish events



Finally, you need to publish the events from the Hotel and Flight microservices. You can use the IBus interface provided by MassTransit to publish the events to the appropriate queue.

Here is an example how I'm publishing the first event on API call:

Publishing Event Saga Pattern



What next?



These are the most necessary steps to implement the SAGA pattern via MassTransit in C#.

But not the only one.

The Persistence part is not included here, where the state can be persisted directly to the database.
Also, no Rollback event was created, for the implementation of which the previous knowledge would be used.

I definitely encourage you to go to GitHub and take a look at the demo project, which after installing RabbitMQ you will be able to run and see what happens.

To activate StateMachine, it is necessary to call the only API that exists in the application (there is swagger support).

That's all from me for today.

Make a coffee and check out source code directly on my GitHub repository.

dream BIG!

Join 10,950+ subscribers to improve your .NET Knowledge.

There are 3 ways I can help you:

Design Patterns Simplified ebook

Go-to resource for understanding the core concepts of design patterns without the overwhelming complexity. In this concise and affordable ebook, I've distilled the essence of design patterns into an easy-to-digest format. It is a Beginner level. Check out it here.


Sponsorship

Promote yourself to 10,950+ subscribers by sponsoring this newsletter.


Join .NET Pro Weekly Newsletter

Every Monday morning, I share 1 actionable tip on C#, .NET & Arcitecture topic, that you can use right away.


Subscribe to
.NET Pro Weekly

Subscribe to the .NET Pro Weekly and be among the 10,950+ subscribers gaining practical tips and resources to enhance your .NET expertise.