3

I need to move my BrokeredMessage to deadletter queue forcefully, if I got a custom exception. Here is my code I have used:

public static async Task Run([ServiceBusTrigger("myqueue", Connection = "myservicebus:cs")]BrokeredMessage myQueueItem, TraceWriter log)
{
    try
    {   
        // process message logic.. 
    }
    catch(CustomException ex)
    {
        //forcefully dead letter if custom exception occurs
        await myQueueItem.DeadLetterAsync();
    }           
}

But, some times I'm getting MessageLockLost, exceptions if I call DeadLetterAsync, AbandonAsync() etc., explicitly in my code even though the lock was not actually lost. Can anyone suggest me, what is the best way to move a brokered message to DeadLetter queue to handle custom exceptions. Thanks.

David Walschots
  • 12,279
  • 5
  • 36
  • 59
Jay
  • 133
  • 2
  • 13
  • I don't think you can do that, the runtime has the LockToken on that message, not your code. You could instantiate your own Service Bus client, but that kind of defeats the purpose a little.. `MaxDeliveryCount` on the SB queue is probably 10 by default, it is configurable though the portal, still doesn't give you custom exceptions. You throw an exception and don't catch it, the delivery count increases, eventually reaches`MaxDeliveryCount`, goes to poison queue. – evilSnobu May 07 '18 at 18:52
  • Exactly what @evilSnobu said. Functions expect either successful processing (no exceptions) to complete your message or exception to retry it. Message will be deadlettered only after deliver count has exceeded the maximum. – Sean Feldman May 07 '18 at 19:10
  • Right, i've removed my answer since he was already using BrokeredMessage. – evilSnobu May 07 '18 at 19:12
  • A cron function (TimeTrigger) with your own Service Bus client would be one way to achieve this, or a continuous WebJob in App Service. – evilSnobu May 07 '18 at 19:14
  • @SeanFeldman But won't `DeadLetter` just work? Yes, Functions will try to `Complete` it, will fail to do so, but `DeadLetter` will stay, right? – Mikhail Shilkov May 07 '18 at 19:27
  • It should work @Mikhail, in theory. But as David pointed out, occasionally it fails. – Sean Feldman May 08 '18 at 00:12
  • @evilSnobu, but until the LockToken expires can't I do any other operations on brokered message? I thought that until `LockedUntilUtc` time up I can do all the operations like Abandon, DeadLetter etc. – Jay May 18 '18 at 09:37

1 Answers1

0

Not exactly what you want for, but a creative workaround:

Add an output Service Bus binding to your function. In place of dead letter'ing the message, add a new message to the output:

public static async Task Run(
    [ServiceBusTrigger("myqueue", Connection = "mysb")] BrokeredMessage myQueueItem, 
    [ServiceBus("mydlq", Connection = "mysb")] IAsyncCollector<BrokeredMessage> dlq, 
    TraceWriter log)
{
    try
    {   
        // process message logic.. 
    }
    catch(CustomException ex)
    {
        // forward to "DLQ" when exception occurs
        var dlqMessage = ...; // you need to create a new message here
        await dlq.AddAsync(dlqMessage);
    }           
}

The original message will be successfully completed.

Note that you need to create a new BrokeredMessage and carefully copy all the data and metadata from the original message. If you have no metadata, maybe it's better to change the type of collector to something simple like IAsyncCollector<string>.

Mikhail Shilkov
  • 34,128
  • 3
  • 68
  • 107
  • Creative :) Also, note that there's a chance for duplicated "dead-lettered" messages. – Sean Feldman May 07 '18 at 22:56
  • @Mikhail Thank you very much. But, Actually I'm not able to understand what will the `output Service Bus (mydlq)` do..I'm doing dead letter queue cleanup by using a timer trigger to analyse the failure count. As per your code should I need to create another queue to store the failed messages? Please correct me If I'm wrong. – Jay May 08 '18 at 12:03
  • 1
    @Jay Yes, you understood correctly, you need a new queue for this scenario. Then you can do anything with it. Sean's concern is valid, so it's not the complete replacement of DLQ. – Mikhail Shilkov May 08 '18 at 13:07