🔥 Pragmatic .NET Code Rules Course is on Presale - 40% off!BUY NOW

SAGA Implementation in C#

March 13 2023

Sponsored

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.


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

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!

For orchestration-based sagas, check out Saga Orchestration Pattern.

Wrapping Up

About the Author

Stefan Djokic is a Microsoft MVP and senior .NET engineer with extensive experience designing enterprise-grade systems and teaching architectural best practices.

There are 3 ways I can help you:

1. Pragmatic .NET Code Rules Course

Stop arguing about code style. In this course you get a production-proven setup with analyzers, CI quality gates, and architecture tests — the exact system I use in real projects. Join here.

Not sure yet? Grab the free Starter Kit — a drop-in setup with the essentials from Module 01.

2. Design Patterns Ebooks

Design Patterns that Deliver — Solve real problems with 5 battle-tested patterns (Builder, Decorator, Strategy, Adapter, Mediator) using practical, real-world examples. Trusted by 650+ developers.

Just getting started? Design Patterns Simplified covers 10 essential patterns in a beginner-friendly, 30-page guide for just $9.95.

3. Join 20,000+ subscribers

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

Join 20,000+ subscribers who mass-improve their .NET skills with actionable tips on C#, Architecture & Best Practices.

Subscribe to
TheCodeMan.net

Subscribe to the TheCodeMan.net and be among the 20,000+ subscribers gaining practical tips and resources to enhance your .NET expertise.