Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save ramonsmits/a1d00516b56d0316e127c1d04ef46b0f to your computer and use it in GitHub Desktop.

Select an option

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
/// <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