Skip to content

Instantly share code, notes, and snippets.

@jsquire
Last active March 14, 2024 21:10
Show Gist options
  • Save jsquire/b25cb9fd3c5002760d703d2b0c216a18 to your computer and use it in GitHub Desktop.
Save jsquire/b25cb9fd3c5002760d703d2b0c216a18 to your computer and use it in GitHub Desktop.
Service Bus: Batch Delete

Service Bus: Batch Delete

Currently, when messages are sent to Service Bus, they can only be removed by reading/completing them or waiting for them to age-out based on the retention policy. This can often become troublesome for applications that accumulate messages in their dead-letter queue when they do not wish to process them, or for applications with messages that are not actionable after a certain age.

Historically, developers have had to write code that loops to perform destructive reads for the messages that they want to remove. While this is relatively straightforward for purge scenarios, it can be tricky to do correctly when the desire is only to remove messages older than a given point in time.

To make this scenario easier for developers, Service Bus is adding a new operation capable of deleting batches of messages and limiting them to a specific time.

Goals

  • Allow developers to purge all messages from a Service Bus entity.
  • Allow developers to delete some number of messages from a Service Bus entity, optionally limited by age.
  • Provide a discoverable client operation for delete rather than using destructive reads.

Why this is needed

Developers have registered consistent feedback since the legacy client libraries were current asking for delete or purge functionality. This request has been around long enough that it is issue #1 in the Azure Service Bus repository, where the service team tracks feature requests.

API View

Usage examples

Delete all messages from an entity (purge)

var connectionString = "<< CONNECTION STRING FOR THE SERVICE BUS NAMESPACE >>";
var entityName = "<< NAME OF THE TARGET ENTITY >>";

await using var client = new ServiceBusClient(connectionString);
await using var receiver = client.CreateReceiver(entityName);

// Purge all messages.
await receiver.DeleteAllMessages();

Delete all messages enqueued before a date

var connectionString = "<< CONNECTION STRING FOR THE SERVICE BUS NAMESPACE >>";
var entityName = "<< NAME OF THE TARGET ENTITY >>";

await using var client = new ServiceBusClient(connectionString);
await using var receiver = client.CreateReceiver(entityName);

// Delete messages more than a year old.
await receiver.DeleteAllMessages(DateTimeOffset.UtcNow.AddYears(-1));

Delete the oldest X messages

var connectionString = "<< CONNECTION STRING FOR THE SERVICE BUS NAMESPACE >>";
var entityName = "<< NAME OF THE TARGET ENTITY >>";

await using var client = new ServiceBusClient(connectionString);
await using var receiver = client.CreateReceiver(entityName);

// Delete the 50 oldest messages
await receiver.DeleteAllMessages(50);

Delete the oldest X messages before a given date

var connectionString = "<< CONNECTION STRING FOR THE SERVICE BUS NAMESPACE >>";
var entityName = "<< NAME OF THE TARGET ENTITY >>";

await using var client = new ServiceBusClient(connectionString);
await using var receiver = client.CreateReceiver(entityName);

// Delete the 50 oldest messages that are more than a month old.
await receiver.DeleteAllMessages(50, DateTimeOffset.UtcNow.AddMonths(-1));
@jsquire
Copy link
Author

jsquire commented Mar 14, 2024

What does purge look like without the convenience method?

var connectionString = "<< CONNECTION STRING FOR THE SERVICE BUS NAMESPACE >>";
var entityName = "<< NAME OF THE TARGET ENTITY >>";

await using var client = new ServiceBusClient(connectionString);
await using var receiver = client.CreateReceiver(entityName);

var deleted = 0; 
var batchCount = MaxDeleteMessageCount;
var targetDate = DateTimeOffset.UtcNow;

// We only want to make an attempt if the exact number of messages requested was deleted.
// Anything less means there were not enough messages eligible for deletion.

while (batchCount == MaxDeleteMessageCount)
{
   batchCount = await DeleteMessagesAsync(MaxDeleteMessageCount, targetDate , cancellationToken).ConfigureAwait(false);
   deleted += batchCount;
}

Console.WriteLine($" There were {deleted} messages deleted.");

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment