How do I delete a DeadLetter message on an Azure Service Bus Topic

11k views Asked by At

I'm writing a piece of code which will allow us to:

  1. View a list of all dead letter messages that exist within an Azure Service Bus Topic (Peek)
  2. Fix and send them back to the Topic
  3. Delete them from the dead letter queue upon resending.

I have no issues with the first 2 points; using the Peek receive mode I can show a list of messages and we can edit and resend with no issues.

The problem comes when I want to actually delete the message from the dead letter queue.

How do we do this on a message by message level? We may only want to delete 2 of the messages residing in the dead letter queue and keep the others for reviewing at a later stage. Does calling .Complete() on a message in the dead letter queue remove it like it does in the main subscription?

For reference; here is our code for getting the SubscriptionClient for the dead letter queue:

private SubscriptionClient GetOrCreateSubscriptionClient(string connectionString)
{
    if (!NamespaceManager.TopicExists(_topicName))
    {
        NamespaceManager.CreateTopic(new TopicDescription(_topicName)
        {
            MaxSizeInMegabytes = 5120,
            DefaultMessageTimeToLive = TimeSpan.FromSeconds(DEFAULT_LOCK_DURATION_IN_SECONDS)
        });
    }

    if (!NamespaceManager.SubscriptionExists(_topicName, _subscriptionName))
    {
        NamespaceManager.CreateSubscription(_topicName, _subscriptionName);
    }

    var deadLetterPath = SubscriptionClient.FormatDeadLetterPath(_topicName, _subscriptionName);

    var client = SubscriptionClient.CreateFromConnectionString(
        connectionString, deadLetterPath, _subscriptionName, ReceiveMode.PeekLock);

    return client;

}
3

There are 3 answers

0
MikeWo On BEST ANSWER

Yes, calling complete on the reference to the brokered message you receive from the dead letter queue will remove it from the dead letter queue.

2
pberggreen On

Here is how you can get a list of all messages in the dead letter queue:

public async Task<IEnumerable<BrokeredMessage>> GetDeadLetterMessagesAsync(string connectionString,
    string queueName)
{
    var queue = QueueClient.CreateFromConnectionString(connectionString, QueueClient.FormatDeadLetterPath(queueName));
    var messageList = new List<BrokeredMessage>();
    BrokeredMessage message;
    do
    {
        message = await queue.PeekAsync();
        if (message != null)
        {
            messageList.Add(message);
        }
    } while (message != null);
    return messageList;
}

Using the SequenceNumber you can then delete a specific message:

public async Task DeleteDeadLetterMessageAsync(string connectionString, string queueName, long sequenceNumber)
{
    var deadLetterQueue = QueueClient.CreateFromConnectionString(connectionString, QueueClient.FormatDeadLetterPath(queueName));
    var msg = await deadLetterQueue.PeekAsync(sequenceNumber);
    if (msg.SequenceNumber == sequenceNumber)
    {
        msg = await deadLetterQueue.ReceiveAsync();
        await msg.CompleteAsync();
    }
}

Please note that Peek may return another message if there isn't any message with the specified SequenceNumber. Therefore you'll need to check the SequenceNumber, so that you don't delete the wrong message.

0
pberggreen On

Updated code to delete a message from the dead letter queue using the new ServiceBusClient from azure.messaging.servicebus:

public async Task DeleteDeadLetterMessageAsync(string connectionString, string queueName, long sequenceNumber)
{
    var serviceBusClient = new ServiceBusClient(connectionString);
    var receiverOptions = new ServiceBusReceiverOptions { SubQueue = SubQueue.DeadLetter };
    var receiver = serviceBusClient.CreateReceiver(queueName, receiverOptions);
    var msg = await receiver.PeekMessageAsync(sequenceNumber);
    if (msg.SequenceNumber == sequenceNumber)
    {
        msg = await receiver.ReceiveMessageAsync();
        await receiver.CompleteMessageAsync(msg);
    }
}