user989988
user989988

Reputation: 3726

lock is invalid exception in Azure Service Bus

I have an Azure Function with the following content in host.json:

{
  "version": "2.0",
  "functionTimeout": "01:00:00",
  "extensions": {
    "serviceBus": {
      "SessionHandlerOptions": {
        "MaxAutoRenewDuration": "01:00:00",
        "MaxLockDuration": "01:00:00",
        "MessageWaitTimeout": "01:00:00",
        "MaxConcurrentSessions": 1,
        "AutoComplete": false
      }
    }
  },
  "logging": {
    "applicationInsights": {
      "samplingExcludedTypes": "Request",
      "samplingSettings": {
        "isEnabled": true
      }
    }
  }
}

On running this function, I see the following exception:

The lock supplied is invalid. Either the lock expired, or the message has already been removed from the queue.

The lock supplied is invalid. Either the lock expired, or the message has already been removed from the queue suggests to set AutoComplete to false. I have already added a property in host.json which sets AutoComplete to false. What am I missing?

Code:

        public async Task Run([ServiceBusTrigger("queuename", Connection = "cn")] Message message,
                              MessageReceiver messageReceiver,
                              [DurableClient] IDurableOrchestrationClient starter,
                              ILogger log)
        {
            var syncJob = JsonConvert.DeserializeObject<Job>(Encoding.UTF8.GetString(message.Body));
            try
            {
                await starter.StartNewAsync(nameof(OrchestratorFunction), syncJob);
                await messageReceiver.CompleteAsync(message.SystemProperties.LockToken);
            }
            catch (Exception ex)
            {
                await messageReceiver.DeadLetterAsync(message.SystemProperties.LockToken, deadLetterReason: ex.Message);
            }
            await _loggingRepository.LogMessageAsync(new LogMessage { Message = $"{nameof(StarterFunction)} function completed" });
        }

Upvotes: 0

Views: 487

Answers (1)

suziki
suziki

Reputation: 14111

I notice you use "AutoComplete": false. Are you sure you put the complete method in the end of your function? I think you should move the 'complete' method to the end, or just set AutoComplete to true. The function will automatically refresh the lock expiration time to keep it available under normal circumstances. But once you use the 'complete' method, the function will generate the last lock, and if your subsequent logic exceeds the lock time, a lock expiration exception will be thrown. You can look at the following code and compare using complete and not using complete:

using System;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Azure.ServiceBus;
using Microsoft.Azure.ServiceBus.Core;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Host;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;

namespace FunctionApp71
{
    public static class Function1
    {
        [FunctionName("Function1")]
        public static async Task Run([ServiceBusTrigger("queuename", Connection = "cn")] Message message, MessageReceiver messageReceiver, [ServiceBus("queuename", Connection = "cn")] IAsyncCollector<Message> queue, ILogger logger)
        {
            logger.LogInformation("When the message comes in, the expire time is: "+message.SystemProperties.LockedUntilUtc.ToString());//Now the time is 2/4/2021 8:29:00 AM

            Thread.Sleep(6000);

            logger.LogInformation("After 6 seconds, the expired time is :"+message.SystemProperties.LockedUntilUtc.ToString());//The time of the lock is renewed, so now the time is 2/4/2021 8:29:04 AM

            //When you complete the message, there is no way to renew the lock because the lock is not exist(Azure function stop renew the lock.).
            await messageReceiver.CompleteAsync(message.SystemProperties.LockToken);
            logger.LogInformation("After complete the message, the expired time is :"+message.SystemProperties.LockedUntilUtc.ToString());//Now the time is still 2/4/2021 8:29:04 AM

            Thread.Sleep(6 * 1000);//Your try catch is here.

            logger.LogInformation("After complete message and 6 seconds later, the expired time is :"+message.SystemProperties.LockedUntilUtc.ToString());
        }
    }
}

enter image description here

Upvotes: 1

Related Questions