public override async Task InvokeAsync(IPipeContext context, CancellationToken token) { var respondCfg = GetResponseConfig(context); var correlationId = GetCorrelationid(context); var dedicatedConsumer = GetDedicatedConsumer(context); var responseTsc = new TaskCompletionSource <BasicDeliverEventArgs>(); IBasicConsumer consumer; if (dedicatedConsumer) { consumer = await ConsumerFactory.CreateConsumerAsync(token : token); ConsumerFactory.ConfigureConsume(consumer, respondCfg.Consume); } else { consumer = await ConsumerFactory.GetConfiguredConsumerAsync(respondCfg.Consume, token : token); } var responses = AllResponses.GetOrAdd(consumer, c => { var pendings = new ConcurrentDictionary <string, TaskCompletionSource <BasicDeliverEventArgs> >(); c.OnMessage((sender, args) => { if (!pendings.TryRemove(args.BasicProperties.CorrelationId, out var tsc)) { return; } tsc.TrySetResult(args); }); return(pendings); } ); context.Properties.Add(PipeKey.Consumer, consumer); responses.TryAdd(correlationId, responseTsc); await Next.InvokeAsync(context, token); token.Register(() => responseTsc.TrySetCanceled()); await responseTsc.Task; Logger.LogInformation("Message '{messageId}' for correlation id '{correlationId}' received.", responseTsc.Task.Result.BasicProperties.MessageId, correlationId); if (dedicatedConsumer) { Logger.LogInformation("Disposing dedicated consumer on queue {queueName}", respondCfg.Consume.QueueName); consumer.Model.Dispose(); AllResponses.TryRemove(consumer, out _); } context.Properties.Add(PipeKey.DeliveryEventArgs, responseTsc.Task.Result); try { await ResponsePipe.InvokeAsync(context, token); } catch (Exception e) { Logger.LogError(e, "Response pipe for message '{messageId}' executed unsuccessfully.", responseTsc.Task.Result.BasicProperties.MessageId); throw; } }