We have a message that can run for up to 1 hour. It needs to be processed only once. We are getting issues where the message is becoming available to other processors however when we attempt to complete the message.
Here is the setup in service bus:
We setup the service bus in the following way:
var options = new ServiceBusProcessorOptions
{
AutoCompleteMessages = false,
MaxConcurrentCalls = 1,
PrefetchCount = 0,
ReceiveMode = ServiceBusReceiveMode.PeekLock,
MaxAutoLockRenewalDuration = TimeSpan.FromHours(2),
};
We then handle the message in the following way:
private async Task HandleMessageAsync(ProcessMessageEventArgs processMessageEventArgs)
{
try
{
var rawMessageBody = Encoding.UTF8.GetString(processMessageEventArgs.Message.Body);
_logger.LogInformation("Received message {MessageId} with body {MessageBody}",
processMessageEventArgs.Message.MessageId, rawMessageBody);
var repoRequest = JsonConvert.DeserializeObject<TMessage>(rawMessageBody);
if (repoRequest != null)
{
await ProcessMessage(repoRequest, processMessageEventArgs.Message.MessageId,
processMessageEventArgs.Message.ApplicationProperties,
processMessageEventArgs.CancellationToken);
}
else
{
_logger.LogError(
"Unable to deserialize to message contract {ContractName} for message {MessageBody}",
typeof(TMessage), rawMessageBody);
}
_logger.LogInformation("Message {MessageId} processed", processMessageEventArgs.Message.MessageId);
await processMessageEventArgs.CompleteMessageAsync(processMessageEventArgs.Message);
}
catch (Exception ex)
{
await processMessageEventArgs.AbandonMessageAsync(processMessageEventArgs.Message);
_logger.LogError(ex, "Unable to handle message");
}
}
However we are getting constant ServiceBusReceiver.RenewMessageLock exceptions along the way which is fine as the message keeps processing. However at the end of the message when we manually call await processMessageEventArgs.CompleteMessageAsync(processMessageEventArgs.Message); it is failing with
Azure.Messaging.ServiceBus.ServiceBusException: The lock supplied is invalid. Either the lock expired, or the message has already been removed from the queue. For more information please see https://aka.ms/ServiceBusExceptions . Reference:xxxxxxx, TrackingId:xxxxx, SystemTracker:gi::G9:4521499:amqps://xxxxxx.servicebus.windows.net/-eb5b7cf4;25:30:31:source(address:/xxxxxx,filter:[]), bi::in-connection1648(G9-96965)::session1654::link417153, Timestamp:2025-02-05T11:37:31 (MessageLockLost). For troubleshooting information, see https://aka.ms/azsdk/net/servicebus/exceptions/troubleshoot. at Azure.Messaging.ServiceBus.Amqp.AmqpReceiver.DisposeMessageAsync(Guid lockToken, Outcome outcome, DispositionStatus disposition, TimeSpan timeout, IDictionary
2 propertiesToModify, String deadLetterReason, String deadLetterDescription) at Azure.Messaging.ServiceBus.Amqp.AmqpReceiver.CompleteInternalAsync(Guid lockToken, TimeSpan timeout) at Azure.Messaging.ServiceBus.Amqp.AmqpReceiver.<>c.<<CompleteAsync>b__47_0>d.MoveNext() --- End of stack trace from previous location --- at Azure.Messaging.ServiceBus.ServiceBusRetryPolicy.<>c__221.<b__22_0>d.MoveNext() --- End of stack trace from previous location --- at Azure.Messaging.ServiceBus.ServiceBusRetryPolicy.RunOperation[T1,TResult](Func4 operation, T1 t1, TransportConnectionScope scope, CancellationToken cancellationToken, Boolean logTimeoutRetriesAsVerbose) at Azure.Messaging.ServiceBus.ServiceBusRetryPolicy.RunOperation[T1,TResult](Func4 operation, T1 t1, TransportConnectionScope scope, CancellationToken cancellationToken, Boolean logTimeoutRetriesAsVerbose) at Azure.Messaging.ServiceBus.ServiceBusRetryPolicy.RunOperation[T1](Func`4 operation, T1 t1, TransportConnectionScope scope, CancellationToken cancellationToken) at Azure.Messaging.ServiceBus.Amqp.AmqpReceiver.CompleteAsync(Guid lockToken, CancellationToken cancellationToken) at Azure.Messaging.ServiceBus.ServiceBusReceiver.CompleteMessageAsync(ServiceBusReceivedMessage message, CancellationToken cancellationToken)
What should we be doing differently. I know that even though MaxAutoLockRenewalDuration is set to 2 hours, Azure doesn't guarantee renewal under all conditions. But how should we be handling this?


RenewMessageLockAsyncperiodically while processing the message. If this is a rare issue use explicit lock renewal or if this happens all the time: Use a tracking database or the Inbox pattern as @SeanFeldman and @VladDX said.RenewMessageLockAsyncor an app does. When a lock is lost in a scenario like this, it generally is because the service state is lost, not that renewal was not attempted.