How in MediatR we can have events (Notifications) async and completely real Parallel


When you use MediatR, it gives you the feature that you can send Notifications or Events. MediatR executes all notifications in sequence and in sync. The total response time is similar to the following equation.

The default implementation of Publish loops through the notification handlers and awaits each one. This ensures each handler is run after one another.

ResponseTime = (Behaviors1 time + Behaviors2 time + ….) + (CommandHandler time) + (Notifications1 time + Notifications2 time + ….)


Consider a scenario where a request for an order from the Client reaches your controller. The controller uses MediatR to send its Command. This command is to create an order. MediatR sends the command to CommandHandler.

After creating the order, you want to send several events, which include: sending SMS and emails to the user, sending events in MessageBroker that other microservices will notice. These 3 tasks are time-consuming tasks and are among the IO tasks that are connected to the external provider.

The first solution

In CommandHandler, after creating the order, send the SMS and email and publish it in MessageBroker. Well, this is not the right solution. First of all, if the provider slows down the email and gets out of reach, we have a problem. We do not have the possibility of compensatory operations for them. We have to keep the Client request open to complete the IO work. Notifications in MediatR can be used to do this. Because MediatR syncs all notifications in a row, it means that if notifications are slow, the request stays open until it’s done.

The second solution Perform IO tasks async and Parallel. We have the ability to execute Notifications the way we want with a little change.

Talk about rubbing salt in my wounds — d’oh!


To do this, we must follow the steps below:


1- First we have to make our Mediator from the base class

public class CustomMediator : Mediator
{
    private Func<IEnumerable<Func<INotification, CancellationToken, 
    Task>>, INotification, CancellationToken, Task> _publish;
    
    public CustomMediator(ServiceFactoryserviceFactory, 
    Func<IEnumerable<Func<INotification, CancellationToken, Task>>, 
    INotification, CancellationToken, Task> publish) : 
    base(serviceFactory)    
    {
        _publish=publish