示例#1
0
        public async Task <string> PutMessagesBack()
        {
            if (_semaphoreSlim.CurrentCount == 0)
            {
                throw new Exception($"Cannot start the process because it was already started and not yet finished.");
            }

            await _semaphoreSlim.WaitAsync(TimeSpan.FromMinutes(10));

            try
            {
                var factory = new ConnectionFactory {
                    Uri = new Uri(_brokerSettingsBase.MtRabbitMqConnString, UriKind.Absolute)
                };
                await _log.WriteInfoAsync(nameof(RabbitPoisonHandingService), nameof(PutMessagesBack),
                                          $"Trying to connect to {factory.Endpoint} ({_rabbitMqSubscriptionSettings.ExchangeName})");

                _connection = factory.CreateConnection();

                var publishingChannel   = _connection.CreateModel();
                var subscriptionChannel = _connection.CreateModel();
                _channels.AddRange(new[] { publishingChannel, subscriptionChannel });

                var publishingArgs = new Dictionary <string, object>()
                {
                    { "x-dead-letter-exchange", _rabbitMqSubscriptionSettings.DeadLetterExchangeName }
                };

                subscriptionChannel.QueueDeclare(PoisonQueueName,
                                                 _rabbitMqSubscriptionSettings.IsDurable, false, false, null);

                var messagesFound     = subscriptionChannel.MessageCount(PoisonQueueName);
                var processedMessages = 0;
                var result            = "Undefined";

                if (messagesFound == 0)
                {
                    result = "No messages found in poison queue. Terminating the process.";

                    await _log.WriteWarningAsync(nameof(RabbitPoisonHandingService), nameof(PutMessagesBack),
                                                 $"No messages found in poison queue. Terminating the process.");

                    FreeResources();
                    return(result);
                }
                else
                {
                    await _log.WriteInfoAsync(nameof(RabbitPoisonHandingService), nameof(PutMessagesBack),
                                              $"{messagesFound} messages found in poison queue. Starting the process.");
                }

                publishingChannel.QueueDeclare(_rabbitMqSubscriptionSettings.QueueName,
                                               _rabbitMqSubscriptionSettings.IsDurable, false, false, publishingArgs);

                var consumer = new EventingBasicConsumer(subscriptionChannel);
                consumer.Received += (ch, ea) =>
                {
                    var message = _brokerApplication.RepackMessage(ea.Body);

                    if (message != null)
                    {
                        try
                        {
                            IBasicProperties properties = null;
                            if (!string.IsNullOrEmpty(_brokerApplication.RoutingKey) ||
                                ea.BasicProperties?.Headers?.Count > 0)
                            {
                                properties = new BasicProperties();
                                if (!string.IsNullOrEmpty(_brokerApplication.RoutingKey))
                                {
                                    properties.Type = _brokerApplication.RoutingKey;
                                }
                                if (ea.BasicProperties?.Headers?.Count > 0)
                                {
                                    properties.Headers = ea.BasicProperties.Headers;
                                }
                            }

                            publishingChannel.BasicPublish(_rabbitMqSubscriptionSettings.ExchangeName,
                                                           _brokerApplication.RoutingKey ?? "", properties, message);

                            subscriptionChannel.BasicAck(ea.DeliveryTag, false);

                            processedMessages++;
                        }
                        catch (Exception e)
                        {
                            _log.WriteErrorAsync(nameof(RabbitPoisonHandingService), nameof(PutMessagesBack), $"Error resending message: {e.Message}", e);
                        }
                    }
                };

                var sw = new Stopwatch();
                sw.Start();

                var tag = subscriptionChannel.BasicConsume(PoisonQueueName, false,
                                                           consumer);

                await _log.WriteInfoAsync(nameof(RabbitPoisonHandingService), nameof(PutMessagesBack),
                                          $"Consumer {tag} started.");

                while (processedMessages < messagesFound)
                {
                    Thread.Sleep(100);

                    if (sw.ElapsedMilliseconds > 30000)
                    {
                        await _log.WriteWarningAsync(nameof(RabbitPoisonHandingService), nameof(PutMessagesBack),
                                                     $"Messages resend takes more than 30s. Terminating the process.");

                        break;
                    }
                }

                result =
                    $"Messages resend finished. Initial number of messages {messagesFound}. Processed number of messages {processedMessages}";

                await _log.WriteInfoAsync(nameof(RabbitPoisonHandingService), nameof(PutMessagesBack), result);

                FreeResources();

                return(result);
            }
            catch (Exception exception)
            {
                var result =
                    $"Exception [{exception.Message}] thrown while putting messages back from poison to queue {_rabbitMqSubscriptionSettings.QueueName}. Stopping the process.";

                await _log.WriteErrorAsync(nameof(RabbitPoisonHandingService), nameof(PutMessagesBack), result, exception);

                return(result);
            }
        }