question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

how to use the publish-strategies of MediatR 12.0

See original GitHub issue

I don’t understand how to use the publish-strategies of MediatR, can anyone give me an example?

public static async Task DispatchDomainEvents(this IMediator mediator, DbContext context,List<DomainEvent> deletedDomainEvents)
    {
        // If the delete domain events list has a value publish it first.
        if (deletedDomainEvents.Any())
        {
            foreach (var domainEvent in deletedDomainEvents)
                await mediator.Publish(domainEvent);
        }

        var entities = context.ChangeTracker
            .Entries<BaseEntity>()
            .Where(e => e.Entity.DomainEvents.Any())
            .Select(e => e.Entity);

        var domainEvents = entities
            .SelectMany(e => e.DomainEvents)
            .ToList();

        entities.ToList().ForEach(e => e.ClearDomainEvents());

        foreach (var domainEvent in domainEvents)
            await mediator.Publish(domainEvent);
    }

I want to use the PublishStrategy.ParallelNoWait strategy to send notifications.

Issue Analytics

  • State:closed
  • Created 7 months ago
  • Comments:8 (4 by maintainers)

github_iconTop GitHub Comments

3reactions
mkidsc1603commented, Mar 7, 2023

Thanks, I resolve it !

    public class TestEvent: BaseEvent
    {
    }
    
    public abstract class BaseEvent : INotification
    {
        public PublishStrategy PublishStrategy { get; set; } = PublishStrategy.Async;
    }

    public enum PublishStrategy
    {
        SyncContinueOnException = 0,
        SyncStopOnException = 1,
        Async = 2,
        ParallelNoWait = 3,
        ParallelWhenAll = 4,
        ParallelWhenAny = 5,
    }

then publish like below:

await _mediator.Publish(new TestEvent() { PublishStrategy = PublishStrategy.ParallelNoWait }, cancellationToken);

Finally, CustomPublisher.cs

    internal class CustomPublisher : INotificationPublisher
    {
        public async Task Publish(IEnumerable<NotificationHandlerExecutor> handlerExecutors, INotification notification, CancellationToken cancellationToken)
        {
            if (notification is BaseEvent)
            {
                BaseEvent e = (BaseEvent)notification;

                if (e.PublishStrategy == PublishStrategy.Async)
                {
                    await AsyncContinueOnException(handlerExecutors, notification, cancellationToken);
                }
                else if (e.PublishStrategy == PublishStrategy.SyncStopOnException)
                {
                    await SyncStopOnException(handlerExecutors, notification, cancellationToken);
                }
                else if (e.PublishStrategy == PublishStrategy.SyncContinueOnException)
                {
                    await SyncContinueOnException(handlerExecutors, notification, cancellationToken);
                }
                else if(e.PublishStrategy == PublishStrategy.ParallelNoWait)
                {
                    ParallelNoWait(handlerExecutors, notification, cancellationToken);
                }
                else if (e.PublishStrategy == PublishStrategy.ParallelWhenAny)
                {
                    ParallelWhenAny(handlerExecutors, notification, cancellationToken);
                }
                else if(e.PublishStrategy == PublishStrategy.ParallelWhenAll)
                {
                    ParallelWhenAll(handlerExecutors, notification, cancellationToken);
                }
                else
                {
                    throw new ArgumentException("Unknown publish strategy.");
                }
            }
            else
            {
                throw new ArgumentException("Notification event class should inherit BaseEvent.");
            }
        }

        private Task ParallelWhenAll(IEnumerable<NotificationHandlerExecutor> handlers, INotification notification, CancellationToken cancellationToken)
        {
            var tasks = new List<Task>();

            foreach (var handler in handlers)
            {
                tasks.Add(Task.Run(() => handler.HandlerCallback(notification, cancellationToken)));
            }

            return Task.WhenAll(tasks);
        }

        private Task ParallelWhenAny(IEnumerable<NotificationHandlerExecutor> handlers, INotification notification, CancellationToken cancellationToken)
        {
            var tasks = new List<Task>();

            foreach (var handler in handlers)
            {
                tasks.Add(Task.Run(() => handler.HandlerCallback(notification, cancellationToken)));
            }

            return Task.WhenAny(tasks);
        }

        private Task ParallelNoWait(IEnumerable<NotificationHandlerExecutor> handlers, INotification notification, CancellationToken cancellationToken)
        {
            foreach (var handler in handlers)
            {
                Task.Run(() => handler.HandlerCallback(notification, cancellationToken));
            }

            return Task.CompletedTask;
        }

        private async Task AsyncContinueOnException(IEnumerable<NotificationHandlerExecutor> handlers, INotification notification, CancellationToken cancellationToken)
        {
            var tasks = new List<Task>();
            var exceptions = new List<Exception>();

            foreach (var handler in handlers)
            {
                try
                {
                    tasks.Add(handler.HandlerCallback(notification, cancellationToken));
                }
                catch (Exception ex) when (!(ex is OutOfMemoryException || ex is StackOverflowException))
                {
                    exceptions.Add(ex);
                }
            }

            try
            {
                await Task.WhenAll(tasks).ConfigureAwait(false);
            }
            catch (AggregateException ex)
            {
                exceptions.AddRange(ex.Flatten().InnerExceptions);
            }
            catch (Exception ex) when (!(ex is OutOfMemoryException || ex is StackOverflowException))
            {
                exceptions.Add(ex);
            }

            if (exceptions.Any())
            {
                throw new AggregateException(exceptions);
            }
        }

        private async Task SyncStopOnException(IEnumerable<NotificationHandlerExecutor> handlers, INotification notification, CancellationToken cancellationToken)
        {
            foreach (var handler in handlers)
            {
                await handler.HandlerCallback(notification, cancellationToken).ConfigureAwait(false);
            }
        }

        private async Task SyncContinueOnException(IEnumerable<NotificationHandlerExecutor> handlers, INotification notification, CancellationToken cancellationToken)
        {
            var exceptions = new List<Exception>();

            foreach (var handler in handlers)
            {
                try
                {
                    await handler.HandlerCallback(notification, cancellationToken).ConfigureAwait(false);
                }
                catch (AggregateException ex)
                {
                    exceptions.AddRange(ex.Flatten().InnerExceptions);
                }
                catch (Exception ex) when (!(ex is OutOfMemoryException || ex is StackOverflowException))
                {
                    exceptions.Add(ex);
                }
            }

            if (exceptions.Any())
            {
                throw new AggregateException(exceptions);
            }
        }
    }
1reaction
neozhucommented, Feb 16, 2023

Thank you for your reply. if I want to use PublishStrategy.ParallelNoWait: Can I write this right?

public class ParallelNoWaitPublisher : INotificationPublisher
{
    public Task Publish(IEnumerable<NotificationHandlerExecutor> handlerExecutors, INotification notification, CancellationToken cancellationToken)
    {
        foreach (var handler in handlerExecutors)
        {
            Task.Run(() => handler.HandlerCallback(notification, cancellationToken));
        }

        return Task.CompletedTask;
    }
}
Read more comments on GitHub >

github_iconTop Results From Across the Web

Publishing strategies in MediatR | Fati Iseni - Blog
Explore advanced publishing strategies with the MediatR library in .NET applications. This article dives into the Mediator pattern, ...
Read more >
How to change MediatR publish strategy
how is it possible to configure another publishing strategy when using MediatR? basically i need to configure it to use publishingStrategy.
Read more >
MNW #030: How To Publish MediatR Notifications In Parallel
Configuring MediatR Notification Publishing Strategy​​ If you want to use the TaskWhenAllPublisher strategy, you can either: Provide a value for ...
Read more >
MediatR 12.0 Released
This is a pretty big release, with a number of breaking changes. ... Breaking changes include: ... The migration guide includes instructions for ......
Read more >
MediatR Publish and Send Methods
The Publish method enables one-to-many communication by broadcasting messages without expecting a response. It promotes loose coupling, and ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found