Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Azure ServiceBus Queue. I receive the same message several times

I invoke client.Send(brokeredMessage); once, but I receive the message several times. For handle queue I use this code

private static void HandleQueue(string queueName, MessageHandler messageHandler)
        {
            // Create the queue if it does not exist already
            string connectionString =
                Configuration.GetConnectionString("Microsoft.ServiceBus.ConnectionString",false);

            var namespaceManager =
                NamespaceManager.CreateFromConnectionString(connectionString);

            if (!namespaceManager.QueueExists(queueName))
            {
                namespaceManager.CreateQueue(queueName);
            }

            QueueClient client =
                QueueClient.CreateFromConnectionString(connectionString, queueName);

            while (true)
            {
                BrokeredMessage message = client.Receive();

                if (message != null)
                {
                    try
                    {    
                        messageHandler(message);

                        // Remove message from queue
                        message.Complete();
                    }
                    catch (Exception)
                    {
                        // Indicate a problem, unlock message in queue
                        message.Abandon();
                    }
                }
            }
        }

Problem is that BrokeredMessage message = client.Receive(); is invoked several times and return the same message, if execution of messageHandler(message); takes long time. How can i fix it?

like image 472
Daniil Grankin Avatar asked Dec 12 '22 13:12

Daniil Grankin


2 Answers

The message is getting unlocked while you are a processing it. The right place to set the lock timeout for the message is on the QueueDescription http://msdn.microsoft.com/en-us/library/microsoft.servicebus.messaging.queuedescription.lockduration.aspx

The max time allowed here is 5 Minutes, so if you need to process the message for longer then you can call RenewLock on the message to continue to keep it invisible to other consumers. You are right in that calling Complete before you have finished processing is not advisable as if you process crashes then you will not get the message back again.

The above mentioned property of BrokeredMessage.ScheduledEnqueueTimeUtc is used to "delay" when a message shows up to consumers from the Queue. Say you send a message on Day 1 and set the scheduled time to day 2 then the message will not be returned by the Recieve call until Day 2.

like image 109
Abhishek Lal Avatar answered May 10 '23 01:05

Abhishek Lal


There are a few things you should do:

  1. Introduce a sleep time in your While(true) loop. Lets say, Thread.Sleep(30000);
  2. Retrieve the message content and mark the message as complete. And then pass the retrieved content to your message handler instead of the message itself. Waiting for the completion of "messagehanfler" is not a good practice.
  3. If an error occurs inside your message handler during the processing, en-queue another brokered message with same content.
  4. Handle poison messages. Check the Delivery count for every brokered message, and delete the message if delivery count exceeds n times, lets say 5 times.

Hope it helps!

like image 22
Kunal Kapoor Avatar answered May 10 '23 01:05

Kunal Kapoor