4

How do you delete the dead letters in an Azure Service Bus queue?

I can process the messages in the queue ...

var queueClient = QueueClient.CreateFromConnectionString(sbConnectionString, queueName);
while (queueClient.Peek() != null)
{
    var brokeredMessage = queueClient.Receive();
    brokeredMessage.Complete();
}

but can't see anyway to handle the dead letter messages

Jayendran
  • 9,638
  • 8
  • 60
  • 103
SteveC
  • 15,808
  • 23
  • 102
  • 173
  • Possible duplicate of [how to peek and delete a message from deadletter in azureservicebus](http://stackoverflow.com/questions/35191298/how-to-peek-and-delete-a-message-from-deadletter-in-azureservicebus) – Thomas Mar 22 '17 at 20:27
  • See this post: http://stackoverflow.com/questions/35191298/how-to-peek-and-delete-a-message-from-deadletter-in-azureservicebus – Thomas Mar 22 '17 at 20:27

4 Answers4

4

The trick is to get the deadletter path for the queue which you can get by using QueueClient.FormatDeadLetterPath(queueName).

Please try the following:

var queueClient = QueueClient.CreateFromConnectionString(sbConnectionString, QueueClient.FormatDeadLetterPath(queueName));
while (queueClient.Peek() != null)
{
    var brokeredMessage = queueClient.Receive();
    brokeredMessage.Complete();
}
Gaurav Mantri
  • 128,066
  • 12
  • 206
  • 241
  • how would you delete a specific dead letter message, without completing the other ones? For instance, if there are 100k dead letters and one wants to delete the last one, is there a way without looping through 99999 messages? I was looking for a possibility to work with the sequence number, but looks like that allows only to browse and peek. – Devis L. May 26 '21 at 20:48
3
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Microsoft.Azure.ServiceBus;
using Microsoft.Azure.ServiceBus.Core;
using System.Text;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace ClearDeadLetterQ
{
    [TestClass]
    public class UnitTest1
    {

        const string ServiceBusConnectionString = "Endpoint=sb://my-domain.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=youraccesskeyhereyouraccesskeyhere";


        [TestMethod]
        public async Task TestMethod1()
        {
            await this.ClearDeadLetters("my.topic.name", "MySubscriptionName/$DeadLetterQueue");
        }

        public async Task ClearDeadLetters(string topicName, string subscriptionName)
        {
            var messageReceiver = new MessageReceiver(ServiceBusConnectionString, EntityNameHelper.FormatSubscriptionPath(topicName, subscriptionName), ReceiveMode.PeekLock);
            var message = await messageReceiver.ReceiveAsync();
            while ((message = await messageReceiver.ReceiveAsync()) != null)
            {
                await messageReceiver.CompleteAsync(message.SystemProperties.LockToken);
            }
            await messageReceiver.CloseAsync();
        }
    }
}
2

There are some great samples available in our GitHub sample repo (https://github.com/Azure-Samples/azure-servicebus-messaging-samples). The DeadletterQueue project should show you an example of how to do this in your code:

    var dead-letterReceiver = await receiverFactory.CreateMessageReceiverAsync(
            QueueClient.FormatDeadLetterPath(queueName), ReceiveMode.PeekLock);
    while (true)
    {
        var msg = await dead-letterReceiver.ReceiveAsync(TimeSpan.Zero);
        if (msg != null)
        {
            foreach (var prop in msg.Properties)
            {
                Console.WriteLine("{0}={1}", prop.Key, prop.Value);
            }
            await msg.CompleteAsync();
        }
        else
        {
            break;
        }
    }
}

Hope that helps!

0

Open Azure into your target Bus Queue Service.
(Set this value in place of <BUS-QUEUE-NAME> on the code)

Go into the queue you want to delete.
(Set this value in place of <QUEUE-NAME> on the code)

Create a Shared Access Policy and name it: RemoveDeadLetterQueue with checkbox Manage been selected. Copy this Primary Key onto <QUEUE-POLICY-PRIMARYKEY> in this code.

And the code is ready to run.

using Microsoft.Azure.ServiceBus.Core;
using Microsoft.Azure.ServiceBus;

string serviceBusQueue = "<BUS-QUEUE-NAME>";
string serviceBusQueueName = "<QUEUE-NAME>";
string policyName = "RemoveDeadLetterQueue";
string policyPrimaryKey = "<QUEUE-POLICY-PRIMARYKEY>";

var receiver = new MessageReceiver(
    connectionString: $"Endpoint=sb://{serviceBusQueue}.servicebus.windows.net/;SharedAccessKeyName={policyName};SharedAccessKey={policyPrimaryKey}", 
    entityPath: $"{serviceBusQueueName}/$DeadLetterQueue",
    receiveMode: ReceiveMode.ReceiveAndDelete
);

var messages = await receiver.ReceiveAsync(maxMessageCount: 1000);
while(messages != null)
{
    foreach (var message in messages)
    {
        Console.WriteLine($"[Delete Message] ID: {message.MessageId}");
    }

    messages = await receiver.ReceiveAsync(maxMessageCount: 1000);
}

await receiver.CloseAsync();

niek tuytel
  • 899
  • 7
  • 18