Как удалить сообщение DeadLetter в разделе служебной шины Azure

Я пишу кусок кода, который позволит нам:

  1. Просмотр списка всех недоставленных сообщений, которые существуют в разделе служебной шины Azure (Peek)
  2. Исправить и отправить их обратно в тему
  3. Удалите их из очереди недоставленных писем после повторной отправки.

У меня нет проблем с первыми 2 пунктами; используя режим получения Peek, я могу показать список сообщений, и мы можем редактировать и отправлять без проблем.

Проблема возникает, когда я хочу удалить сообщение из очереди недоставленных сообщений.

Как мы можем сделать это на уровне сообщения? Мы можем захотеть удалить только 2 из сообщений, находящихся в очереди недоставленных сообщений, и оставить остальные для последующего просмотра. Звонит .Complete() удалить сообщение в очереди недоставленных писем, как в основной подписке?

Для справки; вот наш код для получения SubscriptionClient для очереди мертвых писем:

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 ответа

Решение

Да, выполнение вызова со ссылкой на сообщение с посредником, полученное из очереди недоставленных сообщений, приведет к удалению его из очереди недоставленных сообщений.

Вот как вы можете получить список всех сообщений в очереди недоставленных сообщений:

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;
}

Используя SequenceNumber, вы можете затем удалить конкретное сообщение:

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();
    }
}

Обратите внимание, что Peek может вернуть другое сообщение, если нет сообщения с указанным SequenceNumber. Поэтому вам нужно проверить SequenceNumber, чтобы вы не удалили неправильное сообщение.

Обновлен код для удаления сообщения из очереди недоставленных сообщений с использованием нового ServiceBusClientиз 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);
    }
}
Другие вопросы по тегам