diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 4b9b5204c..62ee9f622 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,6 +1,6 @@ ### New in 1.2.1 (working version, not released yet) -* *Nothing yet...* +* Fix: Prevent multiple calls of the same async subscribers when dispatching events (by @alexeyfv) ### New in 1.2.0 (released 2025-03-09) diff --git a/Source/EventFlow.Tests/UnitTests/Subscribers/DispatchToEventSubscribersTests.cs b/Source/EventFlow.Tests/UnitTests/Subscribers/DispatchToEventSubscribersTests.cs index 14af8edfb..2b76e6dd6 100644 --- a/Source/EventFlow.Tests/UnitTests/Subscribers/DispatchToEventSubscribersTests.cs +++ b/Source/EventFlow.Tests/UnitTests/Subscribers/DispatchToEventSubscribersTests.cs @@ -122,6 +122,20 @@ public void SubscriberExceptionIsThrownIfConfigured() _logMock.VerifyNoProblems(); } + [Test] + public async Task OnlyOneAsynchronousSubscriberGetCalled() + { + // Arrange + var subscriberMock = ArrangeMultipleAsynchronousSubscribers(); + + // Act + await Sut.DispatchToAsynchronousSubscribersAsync(A>(), CancellationToken.None).ConfigureAwait(false); + + // Assert + subscriberMock.Verify(s => s.HandleAsync(It.IsAny>(), It.IsAny()), Times.Once); + _logMock.VerifyNoProblems(); + } + private Mock> ArrangeSynchronousSubscriber() where TEvent : IAggregateEvent { @@ -146,5 +160,17 @@ private Mock> Arrang return subscriberMock; } + + private Mock> ArrangeMultipleAsynchronousSubscribers() + where TEvent : IAggregateEvent + { + var subscriberMock = new Mock>(); + + _serviceProviderMock + .Setup(r => r.GetService(typeof(IEnumerable>))) + .Returns(new object[] { subscriberMock.Object, subscriberMock.Object, subscriberMock.Object }); + + return subscriberMock; + } } } diff --git a/Source/EventFlow/Subscribers/DispatchToEventSubscribers.cs b/Source/EventFlow/Subscribers/DispatchToEventSubscribers.cs index c7ff1f07b..7d72e5d35 100644 --- a/Source/EventFlow/Subscribers/DispatchToEventSubscribers.cs +++ b/Source/EventFlow/Subscribers/DispatchToEventSubscribers.cs @@ -127,6 +127,8 @@ private async Task DispatchToSubscribersAsync( .ConfigureAwait(false); var subscribers = _serviceProvider.GetServices(subscriberInformation.SubscriberType) .Cast() + .GroupBy(s => s.GetType()) + .Select(g => g.First()) .OrderBy(s => s.GetType().Name) .ToList();