Intro

In the previous post I described how to work with Azure Storage Queue Service and provided simple examples. In this post I will continue to work with Azure Storage Queue Service. I am going to describe more advanced scenarios and showcase them in code.

Prerequisites

Refer to previous posts to get started with Azure Storage Queue Service.

Code

The CloudQueueMessage constructor has several overloads. The first two are very straightforward, it is possible to specify message content as string or as a byte[]. The third one is more complex, most developers don't even know about it existence and don't use it. It contains two parameters messageId and popReceipt.

To prevent other processes from updating a message that has been get-ed, a unique PopReceipt is issued with the GetMessage response. Later UpdateMessage and DeleteMessage calls are required to have this PopReceipt to access the item. This prevents crosstalk or a message resurfacing and being picked up by a second worker, then being updated or deleted by the original worker.

But sometimes it is required to recreate the message, in this case you need to know messageId and popReceipt. After that you can update or delete the original message in a way you want.

Consider the following example, it updates the message in a queue:

queue.AddMessage(new CloudQueueMessage("content"));
var message = queue.GetMessage(TimeSpan.FromSeconds(1));

var newMessage = new CloudQueueMessage(message.Id, message.PopReceipt);
newMessage.SetMessageContent("newMessage");
queue.UpdateMessage(newMessage, TimeSpan.Zero, MessageUpdateFields.Visibility | MessageUpdateFields.Content);

Thread.Sleep(TimeSpan.FromSeconds(2));
CloudQueueMessage currentMessage;
while((currentMessage = queue.GetMessage()) != null)
{
    Console.WriteLine($"{currentMessage.Id}, InertionTime: {currentMessage.InsertionTime}, ExpirationTime: {currentMessage.ExpirationTime}, NextVisibleTime: {currentMessage.NextVisibleTime}, Content: {currentMessage.AsString}, PopReceipt: {currentMessage.PopReceipt}, DequeueCount: {currentMessage.DequeueCount}");
    queue.DeleteMessage(currentMessage);
}

This code will update the message in queue by its Id and PopReceipt.

Take a look on an another example:

queue.AddMessage(new CloudQueueMessage("content"));
var message = queue.GetMessage(TimeSpan.FromSeconds(1));

var newMessage = new CloudQueueMessage(message.Id, message.PopReceipt);
queue.UpdateMessage(newMessage, TimeSpan.Zero, MessageUpdateFields.Visibility);

var anotherNewMessage = new CloudQueueMessage(message.Id, message.PopReceipt);
queue.UpdateMessage(anotherNewMessage, TimeSpan.Zero, MessageUpdateFields.Visibility);

It will throw an exception:

The remote server returned an error: (404) Not Found.

That's because we used an original PopReceipt and it is no longer valid. That's it, you can use a PopReceipt only once to UpdateMessage or DeleteMessage.

A next example will delete the message without constructing a new CloudQueueMessage object.

queue.AddMessage(new CloudQueueMessage("content"));
var message = queue.GetMessage(TimeSpan.FromSeconds(1));
queue.DeleteMessage(message.Id, message.PopReceipt);

Thread.Sleep(TimeSpan.FromSeconds(2));
CloudQueueMessage currentMessage;
while((currentMessage = queue.GetMessage()) != null)
{
    Console.WriteLine($"{currentMessage.Id}, InertionTime: {currentMessage.InsertionTime}, ExpirationTime: {currentMessage.ExpirationTime}, NextVisibleTime: {currentMessage.NextVisibleTime}, Content: {currentMessage.AsString}, PopReceipt: {currentMessage.PopReceipt}, DequeueCount: {currentMessage.DequeueCount}");
    queue.DeleteMessage(currentMessage);
}

It will output nothing, because there are no messages in queue.

Summary

In this post I described how to use messageId and PopReceipt parameters and provided code samples. Using MessageId and PopReceipt it is possible to update or delete a message, but it is not possible to read a message's content. This functionality can be useful in certain cases, but I can't suggest anyone rely on it. Think twice before using it. Keep in mind, that PopReceipt changes after call to UpdateMessage or DeleteMessage.


;