Event Messaging with Mass Transit
I have been learning more about messaging queues that are utilized for async communications between microservices.
In addition, I didn’t want to learn a specific messaging technology (i.e. RabbitMQ or Azure Service Bus,) but instead wanted to learn about some sort of abstraction library that would allow me to write to a message bus interface and then switch the backend technologies if I wanted.
That lead me to the MassTransit project. MassTransit is a .NET library that creates a framework to create an event messaging system that ties in with popular messaging queues such as RabbitMQ or AWS SQS/SNS.
The abstraction allows for an application to write against the MassTransit system and then MassTransit will translate that into any backend system that it is being used.
I watched three livestreams from Chris Patterson, one of the creators of MassTransit. These were great introductory videos that covers the basics of using MassTransit.
The code that was generated during this workshop is found at: MassTransit/Sample-Twitch
Video #1 – MassTransit Starting with Mediator
In this first video Chris introduces MassTransit and creates a simple “order submission” example. We are introduced to a few ideas.
Contracts represent the data that goes inside the event message.
Chris uses interfaces to represent the contracts instead of classes (even though classes will work.) He does this because it restricts the contract to not have any methods beyond the defined properties that store data. MassTransit instantiates dynamic objects of these interfaces when messages are being sent.
The contracts project is kept separate so that all the various services are aware of the contracts that exist in the event messaging system.
Events are handled by both publishers and listeners
In the first video, Chris uses MediatR to handle the sending and delivery of all messages in-memory. This only works when the publisher and listener are in the same application.
In this second video, Chris separates the handler of a message into a separate console application service. Because the publisher and listener are in different services, in-memory is replaced with a popular message queue application called RabbitMQ.
RabbitMQ can be setup simply as a running docker instance
Message are sent by the API web application, sent to RabbitMQ, and then published to the console application to be processed.
Sagas are a very interesting concept with event messaging. The bring in the idea of a state machine, and anything that has a “workflow” of some sort can be setup as a state machine and then messages are handled appropriately in accordance to what state that object is in.
This is easily understood in the case of an online store order. An order has multiple states that go from an initial state to a final state. This could include “order submitted”, “order accepted”, “order fulfilled”, “order shipped”, etc… A state machine exists for that order and then that state machine reacts with each message directed towards it.
Automatonymous is the build-in state machine system in MassTransit
There is a very distinct way that the state “workflow” is setup inside a state machine
Each state machine is identified by a “correlation id”
The image below is an example of how the “workflow” is setup inside a state machine