Jay
Jay

Reputation: 133

Getting MessageLockLost exception on brokered message even though lock was not expired

I have implemented a service bus trigger, my sample code is as below.

   public static async Task Run([ServiceBusTrigger("myqueue", Connection = 
    "myservicebus:cs")]BrokeredMessage myQueueItem, TraceWriter log)
    {
        try
        {   
            if (myQueueItem.LockedUntilUtc <= DateTime.UtcNow)
            {
                log.Info($"Lock expired.");

                return;
            }

            //renew lock if message lock is about to expire.             
            if ((myQueueItem.LockedUntilUtc - DateTime.UtcNow).TotalSeconds <= defaultLock)
            {
                await myQueueItem.RenewLockAsync();

                return true;
            }                

            //Process message logic        

            await myQueueItem.CompleteAsync();           
        }
        catch (MessageLockLostException ex)
        {
            log.Error($"Message Lock lost. Exception: {ex}");

        }
        catch(CustomException ex)
        {
            //forcefully dead letter if custom exception occurs
            await myQueueItem.DeadLetterAsync();
        }           
        catch (Exception ex)
        {
            log.Error($"Error occurred while processing message. Exception: {ex}");

            await myQueueItem.AbandonAsync();
        }
    }

I have set the default lock duration on the queue as 5 minutes. I'm getting message lock lost exception for few requests, even though lock was actually not expired. Request process timings as below:

  1. Service bus trigger fired at: May 07 07:02:14 +00:00 2018 utc
  2. LockedUntilUtc in Brokered message : May 07 07:07:08.0149905 utc
  3. Message lock lost exception occurred at : May 07 07:02:18 +00:00 2018 utc

Can anybody help me to find actually what is wrong with my code. Thanks.

Upvotes: 0

Views: 3408

Answers (1)

Mikhail Shilkov
Mikhail Shilkov

Reputation: 35124

You should not explicitly call CompleteAsync and AbandonAsync in your code. Those methods will be called by Azure Functions runtime automatically based on the result of your function execution (Complete if no exception occurred, Abandon otherwise).

Renewing the lock manually shouldn't be necessary either, runtime should manage that for you. If you are running on Consumption plan, the max duration of function execution is 5 minutes (by default) anyway.

Try removing all the plumbing code and leave only //Process message logic, see if that helps.

Upvotes: 4

Related Questions