private async Task MessageReceivedAsync(QueueMessage <TMessage> message, CancellationToken cancellationToken) { if (!cancellationToken.IsCancellationRequested && !_tasks.Any(t => t.Value.IsFaulted)) { if (Behaviour == AcknowledgeBehaviour.BeforeProcess) { _queueConsumer.AcknowledgeMessage(message.DeliveryTag); } string processingSequenceIdentifier = GetProcessingSequenceIdentifier(message.RoutingKey); if (_processingQueues.ContainsKey(processingSequenceIdentifier)) { // Add a message to the processing queue, and signal the processing thread to alert it to the new message. var processingQueue = _processingQueues[processingSequenceIdentifier]; processingQueue.Queue.Enqueue(message); processingQueue.AutoResetEvent.Set(); } else { // create a new processing queue and kick off a task to process it. var processingQueue = new ProcessingQueue <TMessage>(); processingQueue.Queue.Enqueue(message); _processingQueues[processingSequenceIdentifier] = processingQueue; var t = Task.Run(RunSequentialProcessor(processingQueue, cancellationToken)); _tasks.TryAdd(processingSequenceIdentifier, t); } _logger.Info($"Received new message {message.DeliveryTag}, processor queue length {_processingQueues.First().Value.Queue.Count()}"); } // Remove completed queues var processingQueuesToRemove = new List <string>(); foreach (var processingQueue in _processingQueues) { if (!processingQueue.Value.Queue.Any()) { processingQueue.Value.AutoResetEvent.Set(); processingQueuesToRemove.Add(processingQueue.Key); } } foreach (var processingQueueToRemove in processingQueuesToRemove) { _processingQueues.TryRemove(processingQueueToRemove, out _); _tasks.TryRemove(processingQueueToRemove, out _); } // TODO: is it possible to remove executed tasks from the Task list and processingqueues from the processing queues _logger.Info($"Number of tasks {_tasks.Count()}, number of queues {_processingQueues.Count()}."); }
private async Task MessageReceivedAsync(QueueMessage <TMessage> message, CancellationToken cancellationToken) { using (var performanceLogger = new PerformanceLogger(performanceLoggingMethodName)) { try { if (Behaviour == AcknowledgeBehaviour.BeforeProcess) { _queueConsumer.AcknowledgeMessage(message.DeliveryTag); } await ProcessMessageAsync(message.Message, message.DeliveryTag, cancellationToken, message.RoutingKey); if (Behaviour == AcknowledgeBehaviour.AfterProcess) { _queueConsumer.AcknowledgeMessage(message.DeliveryTag); } if (Behaviour != AcknowledgeBehaviour.Never && Behaviour != AcknowledgeBehaviour.Deferred) { _logger.InfoFormat(Resources.MessageProcessedLogEntry, message.DeliveryTag); } } catch (AlreadyClosedException ex) { _logger.Warn($"The connection to Rabbit was closed while processing message with deliveryTag '{message.DeliveryTag}', error details - '{ex.Message}'."); } catch (FatalErrorException e) { if (Behaviour == AcknowledgeBehaviour.AfterProcess || Behaviour == AcknowledgeBehaviour.Async) { _queueConsumer.NegativelyAcknowledgeAndRequeue(message.DeliveryTag); } _logger.Fatal(Resources.FatalErrorLogEntry, e); } catch (Exception e) { _logger.ErrorFormat(Resources.ProcessingErrorLogEntry, message.DeliveryTag, e); if (Behaviour == AcknowledgeBehaviour.AfterProcess || Behaviour == AcknowledgeBehaviour.Async) { _queueConsumer.NegativelyAcknowledge(message.DeliveryTag); } } } }