コード例 #1
0
        void MigrateQueue(IModel channel, int delayLevel, CancellationToken cancellationToken)
        {
            var currentDelayQueue         = $"nsb.delay-level-{delayLevel:00}";
            var messageCount              = channel.MessageCount(currentDelayQueue);
            var declaredDestinationQueues = new HashSet <string>();

            if (messageCount > 0)
            {
                if (!quietMode)
                {
                    console.Write($"Processing {messageCount} messages at delay level {delayLevel:00}. ");
                }

                int skippedMessages   = 0;
                int processedMessages = 0;

                for (int i = 0; i < messageCount && !cancellationToken.IsCancellationRequested; i++)
                {
                    var message = channel.BasicGet(currentDelayQueue, false);

                    if (message == null)
                    {
                        // Queue is empty
                        break;
                    }

                    if (MessageIsInvalid(message))
                    {
                        skippedMessages++;

                        if (!poisonQueueCreated)
                        {
                            channel.QueueDeclare(poisonMessageQueue, true, false, false);
                            poisonQueueCreated = true;
                        }

                        channel.BasicPublish(string.Empty, poisonMessageQueue, message.BasicProperties, message.Body);
                        channel.WaitForConfirmsOrDie();
                        channel.BasicAck(message.DeliveryTag, false);

                        continue;
                    }

                    var messageHeaders = message.BasicProperties.Headers;
                    var delayInSeconds = (int)messageHeaders[DelayInfrastructure.DelayHeader];
                    var timeSent       = GetTimeSent(message);

                    var(destinationQueue, newRoutingKey, newDelayLevel) = GetNewRoutingKey(delayInSeconds, timeSent, message.RoutingKey, DateTimeOffset.UtcNow);

                    // Make sure the destination queue is bound to the delivery exchange to ensure delivery
                    if (!declaredDestinationQueues.Contains(destinationQueue))
                    {
                        routingTopology.BindToDelayInfrastructure(channel, destinationQueue, DelayInfrastructure.DeliveryExchange, DelayInfrastructure.BindingKey(destinationQueue));
                        declaredDestinationQueues.Add(destinationQueue);
                    }

                    var publishExchange = DelayInfrastructure.LevelName(newDelayLevel);

                    if (messageHeaders != null)
                    {
                        //These headers need to be removed so that they won't be copied to an outgoing message if this message gets forwarded
                        messageHeaders.Remove(DelayInfrastructure.XDeathHeader);
                        messageHeaders.Remove(DelayInfrastructure.XFirstDeathExchangeHeader);
                        messageHeaders.Remove(DelayInfrastructure.XFirstDeathQueueHeader);
                        messageHeaders.Remove(DelayInfrastructure.XFirstDeathReasonHeader);
                    }

                    channel.BasicPublish(publishExchange, newRoutingKey, message.BasicProperties, message.Body);
                    channel.WaitForConfirmsOrDie();
                    channel.BasicAck(message.DeliveryTag, false);
                    processedMessages++;
                }

                if (!quietMode)
                {
                    console.WriteLine($"{processedMessages} successful, {skippedMessages} skipped.");
                }
            }
            else
            {
                if (!quietMode)
                {
                    console.WriteLine($"No messages to process at delay level {delayLevel:00}.");
                }
            }
        }
コード例 #2
0
        public Task Run(string endpointName, string?errorQueue, string?auditQueue, IEnumerable <string> instanceDiscriminators, CancellationToken cancellationToken = default)
        {
            console.WriteLine("Connecting to broker");

            using var connection = connectionFactory.CreateAdministrationConnection();
            using var channel    = connection.CreateModel();

            console.WriteLine("Checking for delay infrastructure v2");

            try
            {
                channel.ExchangeDeclarePassive(DelayInfrastructure.DeliveryExchange);
            }
            catch (OperationInterruptedException)
            {
                console.Error.Write("Fail: Delay infrastructure v2 not found.\n");
                throw;
            }

            console.WriteLine($"Creating queues");

            var receivingAddresses = new List <string>()
            {
                endpointName
            };

            if (instanceDiscriminators.Any())
            {
                receivingAddresses.AddRange(instanceDiscriminators.Select(discriminator => $"{endpointName}-{discriminator}"));
            }

            var sendingAddresses = new List <string>();

            if (!string.IsNullOrWhiteSpace(errorQueue))
            {
                sendingAddresses.Add(errorQueue);
            }

            if (!string.IsNullOrWhiteSpace(auditQueue))
            {
                sendingAddresses.Add(auditQueue);
            }

            routingTopology.Initialize(channel, receivingAddresses, sendingAddresses);

            foreach (var receivingAddress in receivingAddresses)
            {
                routingTopology.BindToDelayInfrastructure(channel, receivingAddress, DelayInfrastructure.DeliveryExchange, DelayInfrastructure.BindingKey(receivingAddress));
            }

            console.WriteLine($"Completed successfully");

            return(Task.CompletedTask);
        }