Search code examples
azure-functionsazureservicebusazure-servicebus-queues

Messagelock token expired when resubmitting message on Azure Service Bus queue


I have an Azure function that has the following simple code:

       public class MyDequeuer
        {
            [FunctionName("SampleMessageExecutor")]
            public static async Task Run(
                    [ServiceBusTrigger("test-queue", AccessRights.Listen, Connection = "ServiceBusConnectionString")]
                    Message inMessage, string locktoken, ILogger log, ExecutionContext ctx)
            { 
               try {
                  some code..
              } catch(Exception e) {
                await inMessage.DeadLetterAsync(locktoken);
              }
            }
}

This works fine. However when I at some point later say maybe 1h later or 24h later go to the deadletter queue and try to repair and resubmit the message from the service bus explorer then I see lots of errors saying that the message locktoken has expired. How are you supposed to deal with a scenario where messages can end up on deadletter and maybe reprocessed hours or days later?

I am using function runtime dotnet core 3.1.


Solution

  • Actually about this problem there is an issue in github:How to intentionally deadletter a message in azure functions v2.

    Firstly there is not DeadLetterAsync method for Message class, fro v2 or higher you should use MessageReceiver to implement it.

    Then is about lock token, cause the service bus trigger function will auto complete the message it will cause exception if you want to DeadLetterAsync by yourself. You need to change the host.json, change the autoComplete to flase, you could refer to this host.json setting.

    The below is my code, throw an exception and DeadLetter.

            [FunctionName("Function1")]
            public static async System.Threading.Tasks.Task RunAsync([ServiceBusTrigger("myqueue",Connection = "ServiceBusConnectionString")]string myQueueItem, MessageReceiver messageReceiver, string lockToken, ILogger log)
            {
    
                    try
                    {
                        throw new Exception();
                    }
                    catch (Exception) { 
                        await messageReceiver.DeadLetterAsync(lockToken);
                        log.LogInformation(myQueueItem+ " is put into deadletter");
                    }
            }
    

    Here is my host.json.

    {
      "version": "2.0",
    
      "extensions": {
        "serviceBus": {
          "prefetchCount": 100,
          "messageHandlerOptions": {
            "autoComplete": false,
            "maxConcurrentCalls": 32,
            "maxAutoRenewDuration": "00:55:00"
          },
          "sessionHandlerOptions": {
            "autoComplete": false,
            "messageWaitTimeout": "00:00:30",
            "maxAutoRenewDuration": "00:55:00",
            "maxConcurrentSessions": 16
          }
        }
      }
    
    }
    

    enter image description here