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()}.");
        }
Пример #2
0
        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);
                    }
                }
            }
        }