Question

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?

Was it helpful?

Solution

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.

OTHER TIPS

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!

Sounds like your message goes back to the queue if it has not been processed within the time allowed (per your description that it only happens when messageHandler runs a long time).

Sounds like you want to increase the visibility timeout of your messages, so that they do not go back to the queue quiet so quickly. With ServiceBus this means pre-calculating the time when the messages re-appears if it hasnt been completed

http://msdn.microsoft.com/en-us/library/microsoft.servicebus.messaging.brokeredmessage.scheduledenqueuetimeutc.aspx

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top