private async ValueTask ConsumeAsync(CancellationToken cancellationToken) { try { await Consumer.ConsumeAsync(Reader.AsStream(true), cancellationToken).ConfigureAwait(false); } catch (OperationCanceledException) { // pass cancellation to completion source ConsumerCompletionSource?.TrySetCanceled(CancellationToken.None); // pass exception to ValueTask throw; } catch (Exception exn) { if (0 == Interlocked.CompareExchange(ref _readerCompleted, 1, 0)) { await Reader.CompleteAsync(exn).ConfigureAwait(false); } // pass exception to completion source ConsumerCompletionSource?.TrySetException(exn); // pass exception to ValueTask throw; } finally { if (0 == Interlocked.CompareExchange(ref _readerCompleted, 1, 0)) { await Reader.CompleteAsync(default).ConfigureAwait(false);
private Task <IRawConsumer> GetOrCreateConsumerAsync(IConsumerConfiguration cfg) { return(_channelFactory .GetChannelAsync() .ContinueWith(tChannel => { var consumerCs = new ConsumerCompletionSource(); if (_consumerCompletionSources.TryAdd(tChannel.Result, consumerCs)) { var newConsumer = _consumerFactory.CreateConsumer(cfg, tChannel.Result); WireUpConsumer(newConsumer, cfg); consumerCs.ConsumerQueues.TryAdd( key: cfg.Queue.FullQueueName, value: newConsumer.Model.BasicConsume(cfg.Queue.FullQueueName, cfg.NoAck, newConsumer) ); _currentConsumer = consumerCs; _logger.LogInformation($"Created consumer on channel '{tChannel.Result.ChannelNumber}' that consumes messages from '{cfg.Queue.FullQueueName}'."); consumerCs.TrySetResult(newConsumer); return consumerCs.Task; } _logger.LogDebug($"Consumer for channel '{tChannel.Result.ChannelNumber}' exists. Using it."); consumerCs = _consumerCompletionSources[tChannel.Result]; if (consumerCs.ConsumerQueues.ContainsKey(cfg.Queue.FullQueueName)) { return consumerCs.Task; } return consumerCs.Task.ContinueWith(t => { lock (consumerCs.Consumer) { if (consumerCs.ConsumerQueues.ContainsKey(cfg.Queue.FullQueueName)) { return t.Result; } consumerCs.ConsumerQueues.TryAdd( key: cfg.Queue.FullQueueName, value: consumerCs.Consumer.Model.BasicConsume(cfg.Queue.FullQueueName, cfg.NoAck, consumerCs.Consumer) ); _logger.LogDebug($"Existign consumer for channel '{tChannel.Result.ChannelNumber}' consumes '{cfg.Queue.FullQueueName}'."); return t.Result; } }); }) .Unwrap()); }