Com And Hosting

A queue allows processing of a message by a single consumer. In contrast to queues, topics and subscriptions provide a one-to-many form of communication in a publish and subscribe pattern. It’s useful for scaling to large numbers of recipients. Each published message is made available to each subscription registered with the topic. Publisher sends a message to a topic and one or more subscribers receive a copy of the message, depending on filter rules set on these subscriptions. The subscriptions can use additional filters to restrict the messages that they want to receive. Publishers send messages to a topic in the same way that they send messages to a queue. But, consumers don’t receive messages directly from the topic. Instead, consumers receive messages from subscriptions of the topic. A topic subscription resembles a virtual queue that receives copies of the messages that are sent to the topic. Consumers receive messages from a subscription identically to the way they receive messages from a queue.

The message-sending functionality of a queue maps directly to a topic and its message-receiving functionality maps to a subscription. Among other things, this feature means that subscriptions support the same patterns described earlier in this section with regard to queues: competing consumer, temporal decoupling, load leveling, and load balancing.

Messages stays in the Topic subscription queue for certain period based on the configuration. However, the eventually move to Dead-Letter queue when the delivery fails after the maximum number of retry. See the image below, in this scenario I have too many deadletters. I want to clear the receive the dead letters and clear the queue from the Topic Subscription using C# in donet core.

 

See the example I wrote in console app to retrieve the messages from the Topic Subscription deadletter queue and complete them as received.

        const string ServiceBusConnectionString = "connection_string_for_service_bus";
        // name of the topic created on the Azure portal
        const string TopicName = "contoso-emp";
        
        static ITopicClient topicClient;

        // the following parameters for receving messages
        const string SubscriptionName = "subscription_name/$deadletterqueue"; 
        static ISubscriptionClient subscriptionClient;
                
        static void Main(string[] args)
        {
            
            ClearingDeadLetterAsync().GetAwaiter().GetResult();
        }

Note subscription_name/$deadletterqueue , you have to add the $deadletterqueue to retrieve the message otherwise it will retrieve the message from the main queue.

Path to the dead-letter queue

You can access the dead-letter queue by using the following syntax:

<queue path>/$deadletterqueue
<topic path>/Subscriptions/<subscription path>/$deadletterqueue

See the message processing method and handler below.

static async Task ClearingDeadLetterAsync()
        {
            
            subscriptionClient = new SubscriptionClient(ServiceBusConnectionString, TopicName, SubscriptionName);
            RegisterOnMessageHandlerAndReceiveMessages();

            Console.ReadKey();
            await subscriptionClient.CloseAsync();

        }

static void RegisterOnMessageHandlerAndReceiveMessages()
        {
            var messageHandlerOptions = new MessageHandlerOptions(ExceptionReceivedHandler)
            {
                MaxConcurrentCalls = 1,
                AutoComplete = false

            };

            subscriptionClient.RegisterMessageHandler(ProcessMessagesAsync, messageHandlerOptions);
        }

        static async Task ProcessMessagesAsync(Message message, CancellationToken token)
        {
            Console.WriteLine($"Received message: SequenceNumber: {message.SystemProperties.SequenceNumber} Body: {Encoding.UTF8.GetString(message.Body)}");

            //complete the message to complete once received
            await subscriptionClient.CompleteAsync(message.SystemProperties.LockToken);

        }

        static Task ExceptionReceivedHandler(ExceptionReceivedEventArgs exceptionReceivedEventArgs)
        {
            Console.WriteLine($"Message handler encountered an exception {exceptionReceivedEventArgs.Exception}");
            var context = exceptionReceivedEventArgs.ExceptionReceivedContext;
            Console.WriteLine("Exception context for troubleshooting:");

            Console.WriteLine($" - Endpoint: {context.Endpoint}");
            Console.WriteLine($" - Entry path: {context.EntityPath}");
            Console.WriteLine($" - Executing Action: {context.Action}");

            return Task.CompletedTask;
        }

Build the application and run. It should receive the messages and remove from the Topic Subscription DeadLetter queue.

 

Happy programming.

One thought on “Removing DeadLetters from Azure Service Bus Topic subscription”

Leave a Reply

Your email address will not be published.