Sponsor: Do you build complex software systems? See how NServiceBus makes it easier to design, build, and manage software systems that use message queues to achieve loose coupling. Get started for free.
Once you start doing in-process request & event dispatching, you’ll soon want to move out-of-process so you can isolate work from the caller/invoker. This is often times the next logical step if you’re using MediatR for commands and especially for events/notifications. Here’s how you can do use the same paradigm for in-process and out-of-process using Brighter and RabbitMQ.
Check out my YouTube channel where I post all kinds of content that accompanies my posts including this video showing you how to move work out-of-process.
For those unfamiliar with MediatR library or the mediator pattern:
In software engineering, the mediator pattern defines an object that encapsulates how a set of objects interact. This pattern is considered to be a behavioral pattern due to the way it can alter the program’s running behavior.
I covered MediatR and why you might want to consider it but also one big drawback in my why use MediatR post.
One of the biggest downside to in-process processing (which MediatR does), is it does isolate the actual handling of a request. This isn’t a problem with MediatR at all, just the nature of it executing in-process.
For example, in the case of ASP.NET Core, you’re tied to the originating HTTP request. If the request your processing throws an exception, that will get bubbled up to ASP.NET Core which will return an HTTP 500 to the client.
Brighter is a command dispatcher and command processor. I’m using it for these examples because if you’re familiar with MediatR, Brighter will seem very similar in terms of the API. It can dispatch requests in-process as well as go out-of-process by using a Message Broker like RabbitMQ.
There’s a whole bunch Brighter can do, but for the purpose of this post, I just want to show you how you can move from In-Process to Out-of-Process rather seamlessly.
In my opinion, using the same paradigm with the same library can be incredibly beneficial. For example, if you’re using an in-process approach for ASP.NET Core routes, you can at a later time decide to move them out-of-process with some rather minor code changes.
Here’s an example of using Brighter in the exact same fashion as using MediatR. This is simply creating a PlaceOrder object and then using Brighters CommandProcessor to send that request. Brighter will then invoke the PlaceOrderHandler.Handle method and pass the PlaceOrder object you created.
If you’re familiar with MediatR, this is very very similar. And as mentioned, this is still in-process.
In the above example, because we’re throwing an InvalidOperationException, this will bubble up and cause ASP.NET Core to return the client an HTTP 500.
Moving work out-of-process means we’re going to execute the work that needs to be done for a request to an entirely different physical process than where the request originated. Because of this, the work will be done asynchronously.
Here are a couple of simple diagrams of how that looks.
There are two processes, the HTTP Server using ASP.NET Core, and a Message Processor. Both of these are separate .NET Console Apps. The Contracts and Implementation projects are class libraries that are reference by both HTTP Server and Message processor.
When an HTTP Request comes to ASP.NET Core, it invokes the OrdersController and the PlaceOrder route action. Instead of doing the work required then, we will use Brighter to send a message to the message broker (RabbitMQ).
Once the message has been sent to RabbitMQ, ASP.NET will immediately continue and the client will immediately receive the HTTP 204 NoContent that we’re returning.
It will no longer get the InvalidOperationException and an HTTP 500 error. This is because we are not doing that work in-process.
Here’s how the message process works:
Brighter is configured in the Message Processor to receive messages from RabbitMQ. Brighter will receive the PlaceOrder request and then execute the PlaceOrderHandler.Handle passing the PlaceOrder object.
The code change to move from in-process to out-of-process is changing one method.
Instead of calling Send() on the CommandProcessor, we’re calling Post().
Mind you, there’s some configuration required in the ASP.NET Core and the MessageProcessor projects. Here’s a sample of the ConfigureServices in the ASP.NET Core Startup class.
Retries & More
One of the nice things about running out-of-process is having the ability to retry on failures. This is pretty straight forward with Brighter by using a UsePolicy attribute on the handle method.
Brighter has a a lot of features that can be found in their docs.
I realize in this post I have not covered the reasons why or when you should move work out-of-process. I’ll be covering those topics more in future blog posts and videos.
The intent with this post was to display Brighter and how a library that handles both in-process and out-of-process can be very beneficial when you need to make the transition.
If you have any questions or comments, let me know in the comments, Twitter, or YouTube.