locked
Handling queue message deletion error RRS feed

  • Question

  • Is there a way to tell whether deleting a queue message failed because the message truly no longer exists vs. a mismatched pop receipt? According to the documentation (http://msdn.microsoft.com/en-us/library/dd179347.aspx), one should return a 404 and one should return a 400, but using the storage client library (in versions 1.2 and 1.3 of the sdk) I am always seeing a 404 with an error code of "MessageNotFound".
    Sunday, February 27, 2011 8:12 PM

Answers

  • Hi,

    #So you're seeing the "PopReceiptMismatch" error when trying to delete a message using a non existent id, as opposed to a pop reciept?

    Here is my test code:

     static void Main(string[] args)
            {
                CloudStorageAccount account = new CloudStorageAccount(
                    new StorageCredentialsAccountAndKey("[xxx]", "[xxxxxxxx]"), false);

                CloudQueueClient queueclient = account.CreateCloudQueueClient();

                var queue = queueclient.GetQueueReference("test0001");
                queue.CreateIfNotExist();

                var queue2 = queueclient.GetQueueReference("test0002");
                queue2.CreateIfNotExist();

                queue.AddMessage(new CloudQueueMessage("hello, queue1"));
                queue.AddMessage(new CloudQueueMessage("hello, queue1, message2"));
                queue2.AddMessage(new CloudQueueMessage("hello, queue2"));

                var message1 = queue.GetMessage();
                var message2 = queue2.GetMessage();
                var queue1message2 = queue.GetMessage();

                // valid format, but not a correct pop receipt for queue1
                try
                {
                    queue.DeleteMessage(message1.Id, message2.PopReceipt);
                }
                catch (Exception ex) // throw 400, 'The specified pop receipt did not match.'
                {
                    Console.WriteLine(ex.Message);
                }

                // valid queue1 popreceipt
                try
                {
                    queue.DeleteMessage(message1.Id, queue1message2.PopReceipt);
                }
                catch (Exception ex) // throw 404 error, 'The specified message does not exist.'
                {
                    Console.WriteLine(ex.Message);
                }

                queue.DeleteMessage(message1);
                queue.DeleteMessage(queue1message2);
                queue2.DeleteMessage(message2);
            }
        }

    #The problem is if the same message is dequeued by another thread first and then given a different pop receipt, the original thread seemingly has no way to detect this...it just looks like the message has already been deleted.

    Sorry, I didn't test this scenario before, and I can confirm what you said. From my understanding, when you try to delete a visibility timeout message( we can check message nextVisibleTime) and get 404 error, it means the message is at least dequeued and handled by another thread/role_instance. To avoid duplicate handling message, since we can hardly control other thread/role_instance, we may consider roleback any changes caused by this visiblity timeout message.

    The documents are not accurate on this issue, as my colleague said, they will be corrected.

    Thanks,


    Mog Liang
    Please mark the replies as answers if they help or unmark if not.
    If you have any feedback about my replies, please contact msdnmg@microsoft.com.
    Microsoft One Code Framework
    • Marked as answer by Zach Parrish Monday, March 14, 2011 11:31 AM
    Monday, March 14, 2011 2:41 AM

All replies

  • Hi Zach,

    I cannot reproduce this issue, based on my test, wrong popreceipt will throw 400 error 'Value for one of the query parameters specified in the request URI is invalid.'

    Here is my test code

            static void Main(string[] args)
            {
                CloudStorageAccount account = new CloudStorageAccount(
                    new StorageCredentialsAccountAndKey("XXXXX", "XXXXXXXXXX"), false);

                CloudQueueClient queueclient = account.CreateCloudQueueClient();

                var queue = queueclient.GetQueueReference("test002");
                queue.CreateIfNotExist();

                queue.AddMessage(
                    new CloudQueueMessage("hello," + DateTime.Now));

                var message = queue.GetMessage();

                try
                {
                    queue.DeleteMessage(message.Id, "123");
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }

                try
                {
                    queue.DeleteMessage(message.Id, message.PopReceipt);
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }

                try
                {
                    queue.DeleteMessage(message.Id, message.PopReceipt);
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }

            }

    If you cannot find the cause of the problem, could you please provide code? I will test on my machine.

    Thanks,

     


    Mog Liang
    Please mark the replies as answers if they help or unmark if not.
    If you have any feedback about my replies, please contact msdnmg@microsoft.com.
    Microsoft One Code Framework
    Monday, February 28, 2011 8:33 AM
  • Mog,

    Thank you for looking into this problem. I tested your code, and I believe the error you are seeing is because "123" is not a valid pop receipt, so it doesn't even get far enough to attempt the deletion. Please retry using a valid pop receipt, such as "0LWU+XSlzQg=", and I think you'll see what I'm talking about.

    Zach

    Monday, February 28, 2011 3:43 PM
  • Hi Zach,

    I can reproduce the issue. I've confirmed with the storage dev team, this is a correct behavior, the queue service would return 400 when popreceipt is not in correct format, and return 404 when the pop receipt was of the correct format but the service did not find the message id with that receipt.

    The document (http://msdn.microsoft.com/en-us/library/dd179347.aspx) doesn't describe the this clearly, it will be updated in future.

    Thanks,


    Mog Liang
    Please mark the replies as answers if they help or unmark if not.
    If you have any feedback about my replies, please contact msdnmg@microsoft.com.
    Microsoft One Code Framework
    Tuesday, March 1, 2011 5:44 AM
  • So to confirm, you are saying the documentation is wrong and there is no way to tell the difference between a message that has been deleted and one that has exceeded the visibility timeout and was then dequeued by a different thread thereby giving it a different pop receipt?

    If so, then can you tell me what the purpose of the queue service error code "PopReceiptMismatch" is as defined here: http://msdn.microsoft.com/en-us/library/dd179446.aspx. In what circumstance would that error code be seen?

    Zach

    Tuesday, March 1, 2011 1:20 PM
  • Hi Zach,

    When visibility timeout exceeds, the original popreceipt is still valid, you could still use it to delete message.

    If the same message is dequeued by different pop receipt and deleted, when using old popreceipt to delete message, you'll get 'message not exist' error.

    As refer to 'PopReceiptMismatch' error, based on my testing, when using a id which is not ever issued by the target queue, delete operation would return this error.

    Thanks,


    Mog Liang
    Please mark the replies as answers if they help or unmark if not.
    If you have any feedback about my replies, please contact msdnmg@microsoft.com.
    Microsoft One Code Framework
    Friday, March 11, 2011 4:26 AM
  • So you're seeing the "PopReceiptMismatch" error when trying to delete a message using a non existent id, as opposed to a pop reciept? Can you provide code that demonstrates this? That seems like a bug to me as the documentation clearly states when you should receive that message:

    "The specified pop receipt did not match the pop receipt for a dequeued message."

    I understand that if the visibility timeout is exceeded I can still use the original pop receipt to delete the message. The problem is if the same message is dequeued by another thread first and then given a different pop receipt, the original thread seemingly has no way to detect this...it just looks like the message has already been deleted.

    The documentation in both places I have already referenced (http://msdn.microsoft.com/en-us/library/dd179347.aspx, and http://msdn.microsoft.com/en-us/library/dd179446.aspx) seems to me to be quite clear that this should be a detectable scenario.

    Zach

    Friday, March 11, 2011 3:23 PM
  • Hi,

    #So you're seeing the "PopReceiptMismatch" error when trying to delete a message using a non existent id, as opposed to a pop reciept?

    Here is my test code:

     static void Main(string[] args)
            {
                CloudStorageAccount account = new CloudStorageAccount(
                    new StorageCredentialsAccountAndKey("[xxx]", "[xxxxxxxx]"), false);

                CloudQueueClient queueclient = account.CreateCloudQueueClient();

                var queue = queueclient.GetQueueReference("test0001");
                queue.CreateIfNotExist();

                var queue2 = queueclient.GetQueueReference("test0002");
                queue2.CreateIfNotExist();

                queue.AddMessage(new CloudQueueMessage("hello, queue1"));
                queue.AddMessage(new CloudQueueMessage("hello, queue1, message2"));
                queue2.AddMessage(new CloudQueueMessage("hello, queue2"));

                var message1 = queue.GetMessage();
                var message2 = queue2.GetMessage();
                var queue1message2 = queue.GetMessage();

                // valid format, but not a correct pop receipt for queue1
                try
                {
                    queue.DeleteMessage(message1.Id, message2.PopReceipt);
                }
                catch (Exception ex) // throw 400, 'The specified pop receipt did not match.'
                {
                    Console.WriteLine(ex.Message);
                }

                // valid queue1 popreceipt
                try
                {
                    queue.DeleteMessage(message1.Id, queue1message2.PopReceipt);
                }
                catch (Exception ex) // throw 404 error, 'The specified message does not exist.'
                {
                    Console.WriteLine(ex.Message);
                }

                queue.DeleteMessage(message1);
                queue.DeleteMessage(queue1message2);
                queue2.DeleteMessage(message2);
            }
        }

    #The problem is if the same message is dequeued by another thread first and then given a different pop receipt, the original thread seemingly has no way to detect this...it just looks like the message has already been deleted.

    Sorry, I didn't test this scenario before, and I can confirm what you said. From my understanding, when you try to delete a visibility timeout message( we can check message nextVisibleTime) and get 404 error, it means the message is at least dequeued and handled by another thread/role_instance. To avoid duplicate handling message, since we can hardly control other thread/role_instance, we may consider roleback any changes caused by this visiblity timeout message.

    The documents are not accurate on this issue, as my colleague said, they will be corrected.

    Thanks,


    Mog Liang
    Please mark the replies as answers if they help or unmark if not.
    If you have any feedback about my replies, please contact msdnmg@microsoft.com.
    Microsoft One Code Framework
    • Marked as answer by Zach Parrish Monday, March 14, 2011 11:31 AM
    Monday, March 14, 2011 2:41 AM