[BUG] Message lock renewal not working for 10+ minutes processin durationg when using different `ServiceBusReceiver` instances for `CompleteMessageAsync` and `RenewMessageLockAsync`
See original GitHub issueLibrary name and version
Azure.Messaging.ServiceBus 7.8.0, 7.8.1 and 7.9.0
Describe the bug
When using transactions and invoking RenewMessageLockAsync
on a different ServiceBusReceiver
and processing durations are over 10 minutes then invoking CompleteMessageAsync
CAN results in a MessageLockLost
if that is the only message concurrently being processed.
A similar bug was reported earlier. This has been fixed in 7.8.0 when invoking invoking CompleteMessageAsync
on the same receiver as CompleteMessageAsync
.
Expected behavior
The client not gets into a faulty state where lock renewal seems to succeed but when CompleteMessageAsync
is invoked that it fails with MessageLockLost
.
Actual behavior
The client can get into a faulty state where:
- any message that will be ack’d via
CompleteMessageAsync
where processing is longer then the queue lock duration will fail - any message that result in a lock renewal via
RenewMessageLockAsync
will incorrectly succeed
Reproduction Steps
var lockDuration = TimeSpan.FromMinutes(5);
var renewalInterval = lockDuration - TimeSpan.FromSeconds(10);
var queueName = "test-" + DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
var cs = Environment.GetEnvironmentVariable("AzureServiceBus_ConnectionString");
var admin = new ServiceBusAdministrationClient(cs);
await admin.CreateQueueAsync(new CreateQueueOptions(queueName) { LockDuration = lockDuration, AutoDeleteOnIdle = TimeSpan.FromMinutes(10) });
var sw = Stopwatch.StartNew();
using var logger = new AzureEventSourceListener((ea, m) => Console.Out.WriteLineAsync($"{sw.Elapsed,-15:g} [{ea.Level,-13}] {m}"), EventLevel.Verbose);
await using var client = new ServiceBusClient(cs, new ServiceBusClientOptions { EnableCrossEntityTransactions = true });
await using var sender = client.CreateSender(queueName);
await sender.SendMessageAsync(new ServiceBusMessage());
await using var receiver = client.CreateReceiver(queueName);
var message = await receiver.ReceiveMessageAsync(); Trace.Assert(message != null);
using var cts = new CancellationTokenSource(TimeSpan.FromMinutes(11));
await RenewLockAsync(message!, cts.Token);
using var ts = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled);
await sender.SendMessageAsync(new ServiceBusMessage());
await receiver.CompleteMessageAsync(message);
ts.Complete();
async Task RenewLockAsync(ServiceBusReceivedMessage message, CancellationToken cancellationToken)
{
var renewLockReceiver = client.CreateReceiver(queueName);
while (!cancellationToken.IsCancellationRequested)
{
var delayTask = await Task.Delay(renewalInterval, cancellationToken)
.ContinueWith(t => t, TaskContinuationOptions.ExecuteSynchronously);
if (delayTask.IsCanceled) return;
await renewLockReceiver.RenewMessageLockAsync(message);
}
}
Environment
- net6
- windows 10
Issue Analytics
- State:
- Created a year ago
- Comments:13 (6 by maintainers)
Top Results From Across the Web
how to renew lock for a very long processing message on ...
The lock renewal time is set to 5 minutes by default. The DeliveryCount of the processed message will not rise if the auto-lock...
Read more >Azure Service Bus message transfers, locks, and settlement
The default value for the lock duration is 1 minute. You can specify a different value for the lock duration at the queue...
Read more >Azure Service Bus lock renewal
Long message processing with Azure Service Bus. ... The lock will be renewed 10 seconds before the LockUntil value from the message.
Read more >Azure Service Bus Essentials — Message Settlement with ...
Renewing the lock duration If a consumer feels like it needs more time to complete a message, it can ask the broker for...
Read more >Azure Service Bus client library for Python - Microsoft .NET
Working with topics and subscriptions. Settle a message after receipt. Automatically renew Message or Session locks. To perform management tasks such as ...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
I think in our case that is actually happening. For example, allowing for a processing concurrency of 10 but then having only a single message in the queue. That means 9 receive operations are waiting for a message. If no messages are in the queue (meaning, the queue is more or less idle) this can happen too.
@JoshLove-msft It seems my repro code was incorrect and I found the difference. I’ve updated the description with the following:
The important question is. Is this actually a supported scenario?
RenewMessageLockAsync
on a differentServiceBusReceiver
instance should result in an exception.