Created
July 3, 2018 13:28
-
-
Save ramonsmits/a1d00516b56d0316e127c1d04ef46b0f to your computer and use it in GitHub Desktop.
NServiceBus behavior that results in incoming messages of the same type to be processed sequentially even though the endpoint is configured for concurrent processing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /// <summary> | |
| /// Usage: | |
| /// endpointConfiguration.Pipeline.Register(new SequentialProcessingByMessageTypeBehavior(), "Processes incoming messages of the same type sequentially."); | |
| /// </summary> | |
| class SequentialProcessingByMessageTypeBehavior : IBehavior<IIncomingPhysicalMessageContext, IIncomingPhysicalMessageContext> | |
| { | |
| TimeSpan Timeout = TimeSpan.FromSeconds(1); | |
| ConcurrentDictionary<string, SemaphoreSlim> semaphores = new ConcurrentDictionary<string, SemaphoreSlim>(); | |
| public async Task Invoke(IIncomingPhysicalMessageContext context, Func<IIncomingPhysicalMessageContext, Task> next) | |
| { | |
| var type = context.MessageHeaders[Headers.EnclosedMessageTypes]; | |
| var semaphore = semaphores.GetOrAdd(type, x => new SemaphoreSlim(1)); | |
| var success = await semaphore.WaitAsync(Timeout) | |
| .ConfigureAwait(false); | |
| if (!success) throw new InvalidOperationException($"Could not obtain semaphore within {Timeout}"); | |
| try | |
| { | |
| await next(context) | |
| .ConfigureAwait(false); | |
| } | |
| finally | |
| { | |
| semaphore.Release(); | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment