I recently deployed some new code to a production Azure Function– feature complete, good to go! This particular function is triggered by an Azure Queue and when I went to check on how things were running later in the day I found over 50,000 messages in the poison queue! Apparently I had an exception in my code, easily fixable (and redeployed) in a few minutes, but what about those poison messages?
It looks like Azure Storage Explorer (app for inspecting Azure storage) doesn’t have support for copying messages from one queue to another – so looks like we need our own tool to do it!
Step 1 – Create a C# Console Project in Visual Studio
I’m using Visual Studio 2017 Update 4 in my example, but it should work in prior versions!
Step 2 – Add the Required References
- Right-click on the project in solution explorer and choose “Manage NuGet Packages”
- Click the “Browse” tab, search for “WindowsAzure.Storage”, choose + install
Step 3 – Write the code!
Here’s the complete code for moving messages from the poison queue back to the original queue! Some potential ways you can optimize and improve the code would be to batch messages (instead of handling 1-by-1), add error handling in case either of the queues don’t exist, add error handling in case adding the message to the original queue fails (then re-add it to the poison queue instead), etc.
using System;
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Queue;
class Program
{
static void Main(string[] args)
{
// Prompt the user for the connection string
Console.WriteLine("Enter the connection string for the Azure storage account:");
var connectionString = Console.ReadLine();
// Prompt the user for the queue name
Console.WriteLine("Enter the name of the Azure Queue to unpoison:");
var queueName = Console.ReadLine();
if (!string.IsNullOrWhiteSpace(connectionString) && !string.IsNullOrWhiteSpace(queueName))
{
// setup the connection to table storage
CloudStorageAccount cloudStorageAccount = CloudStorageAccount.Parse(connectionString);
CloudQueueClient queueClient = cloudStorageAccount.CreateCloudQueueClient();
CloudQueue poisonQueue = queueClient.GetQueueReference(queueName + "-poison");
CloudQueue regularQueue = queueClient.GetQueueReference(queueName);
CloudQueueMessage retrievedMessage = poisonQueue.GetMessage();
while (retrievedMessage != null)
{
// delete the message from the poison queue
poisonQueue.DeleteMessage(retrievedMessage);
// queue up a new message on the original queue
regularQueue.AddMessage(retrievedMessage);
Console.WriteLine("Moved over message from poison queue: " + retrievedMessage.AsString);
// Get the next message for processing
retrievedMessage = poisonQueue.GetMessage();
}
}
else
{
Console.WriteLine("Unable to proceed without the connection string and queue name.");
}
}
}
Let me know your comments & suggestions below!