简体   繁体   中英

In C#, how can I process all RabbitMQ messages currently on the queue?

The basic RabbitMQ tutorial gives an example of how to retrieve messages continuously from a queue:

var factory = new ConnectionFactory() { HostName = "localhost" };
using (var connection = factory.CreateConnection())
{
    using (var channel = connection.CreateModel())
    {
        channel.QueueDeclare("hello", false, false, false, null);

        var consumer = new QueueingBasicConsumer(channel);
        channel.BasicConsume("hello", true, consumer);

        Console.WriteLine(" [*] Waiting for messages." +
                                 "To exit press CTRL+C");
        while (true)
        {
            var ea = (BasicDeliverEventArgs)consumer.Queue.Dequeue();

            var body = ea.Body;
            var message = Encoding.UTF8.GetString(body);
            Console.WriteLine(" [x] Received {0}", message);
        }
    }
}

What I want to do is retrieve all messages which have been placed onto the queue and then stop.

Here are two examples that would solve my problem

  1. If I start my code at 1pm, I want to process all the messages that have been placed on the queue before 1pm.

OR

  1. If I start my code at 13:00:00, and it takes 10 seconds for my code to run, I don't mind if it includes messages placed on the queue between 13:00:00 and 13:00:10, as long as it stops as soon as the queue is empty.

I realize that I can probably put a time stamp in my message and check for that, or I could fiddle with timeout values, but I was wondering if there's any built in way to do this properly.

Thanks in advance.

From the comments it seems that RabbitMQ is not meant for batch processing, so it hasn't been designed for this purpose.

I've also noticed that, when testing the DequeueNoWait method, or attempting to Dequeue with a zero timeout, they didn't work at all, and simply returned null.

The following solution uses QueueDeclare to get a count of existing messages and doesn't require a time stamp or a hacky timeout:

var factory = new ConnectionFactory { HostName = "localhost" };
using (var connection = factory.CreateConnection())
{
    using (var channel = connection.CreateModel())
    {
        var queueDeclareResponse = channel.QueueDeclare(Constants.QueueName, false, false, false, null);

        var consumer = new QueueingBasicConsumer(channel);
        channel.BasicConsume(Constants.QueueName, true, consumer);

        Console.WriteLine(" [*] Processing existing messages.");

        for (int i = 0; i < queueDeclareResponse.MessageCount; i++)
        {
            var ea = (BasicDeliverEventArgs)consumer.Queue.Dequeue();
            var body = ea.Body;
            var message = Encoding.UTF8.GetString(body);
            Console.WriteLine(" [x] Received {0}", message);
        }
        Console.WriteLine("Finished processing {0} messages.", queueDeclareResponse.MessageCount);
        Console.ReadLine();
    }
}

What you can do:

1.) First add a timestamp to the message object

2.) Reject the message if the timestamp is not valid. It is an integrated feature of rabbitmq

Reference

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM