[ 
https://issues.apache.org/jira/browse/CAMEL-25701?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Work on CAMEL-25701 started by shashank.
----------------------------------------
> camel-azure-servicebus - the Camel lock renewer waits for its next run when a 
> message lock expires within 10 seconds, but runs only every 10 to 11 seconds, 
> so locks of long-running exchanges are lost and the messages are delivered 
> again
> --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
>
>                 Key: CAMEL-25701
>                 URL: https://issues.apache.org/jira/browse/CAMEL-25701
>             Project: Camel
>          Issue Type: Bug
>          Components: camel-azure-servicebus
>            Reporter: shashank
>            Assignee: shashank
>            Priority: Major
>
> Since CAMEL-23937 the Service Bus consumer renews the message locks itself in 
> {{PEEK_LOCK}} mode (the default, with the default 
> {{maxAutoLockRenewDuration}} of 5 minutes, sessions disabled): the SDK's own 
> renewal stops when Camel's callback returns, which is immediately for an 
> asynchronous route. {{ServiceBusConsumer}} schedules a {{LockRenewer}} with 
> {{PeriodTaskScheduler.schedulePeriodTask(lockRenewer, 10000)}}, and the 
> renewer renews a lock when {{now + 10 seconds}} is after the lock's expiry 
> ({{LOCK_RENEW_INTERVAL_SECONDS}}, line 347 on main d46d51c24550).
> The period task scheduler is driven by a 1-second timer 
> ({{TimerListenerManager}}), and {{PeriodicTaskWrapper}} runs the task when 
> more than 10000 ms have passed since the last run, so two runs are 10 or 11 
> seconds apart. The window in which the renewer acts is 10 seconds long. When 
> the lock expires between 10 and 11 seconds after a run, that run leaves it 
> alone ("not yet within 10 seconds") and the next run comes after the lock has 
> expired, or so close to the expiry that the renewal request arrives too late. 
> The renewal then fails with a lost lock, the entry is dropped (WARN "Failed 
> to renew lock"), Service Bus delivers the message again to this or another 
> consumer while the first exchange is still being processed, and the final 
> {{complete()}} of the first exchange fails.
> A small exhaustive model of the timing (every sequence of 6 run gaps of 10 or 
> 11 seconds, lock expiry at every 100 ms phase) loses the lock in 6.0% of the 
> cases with the current 10-second margin (11% when the runs come every 11 
> seconds, 1% when they come exactly every 10 seconds: an expiry that falls on 
> a run), and in none with a margin of two intervals. Which gap the scheduler 
> produces depends on sub-millisecond timer jitter. An exchange that is 
> processed for 5 minutes with the default 60-second lock duration crosses 
> about 5 lock periods, so with 6% per period roughly one such exchange in four 
> is delivered twice.
> Trigger: default options ({{PEEK_LOCK}}, {{maxAutoLockRenewDuration}} 5 
> minutes), no sessions, an asynchronous route (the case CAMEL-23937 is about), 
> and an exchange that takes longer than the lock duration of the queue or 
> subscription minus 10 seconds.
> h3. Reproduction
> New test in {{ServiceBusConsumerTest}} (Mockito, no Service Bus): the renewer 
> is captured from the scheduler together with its period; a message whose lock 
> expires 2 seconds after the earliest possible next run ({{period + 2 s}}) is 
> tracked, and the renewer runs once. Waiting for the next run would leave at 
> most 2 seconds, or none. On main the renewer does not renew:
> {noformat}
> Wanted but not invoked:
> renewalClient.renewMessageLock(message);
> {noformat}
> A second new test (a lock that expires in 60 seconds is not renewed) passes 
> on main and with the fix; it guards against renewing too early.
> h3. Proposed fix
> Renew when the lock expires within two intervals (20 seconds) instead of one: 
> every lock is then renewed by a run that comes at least about 9 seconds 
> before it expires. A lock is still renewed about once per lock duration 
> (somewhat earlier than before); with a lock duration of 20 seconds or less it 
> is renewed at every run. No option changes.
> camel-azure-servicebus unit tests with the fix: 79 run, 0 failures, 8 skipped 
> (integration tests). Not run: a real namespace.
> How it was found: comparing the lock renewal timing with the visibility 
> extender of camel-aws2-sqs (which renews when the deadline falls before the 
> next expected run) during a sweep of acknowledge and lock timing; the test 
> and the timing model confirmed it.
> Affected: main (tested). camel-4.23.x and camel-4.22.x (line 336) and 
> camel-4.18.x (line 310) have the same renewer (read, not run).
> Duplicate check (2026-10-16): JIRA text "renewMessageLock" / "lock renewal" 
> with component camel-azure-servicebus (CAMEL-23937, CAMEL-23938 session lock 
> renewal, resolved Not A Problem, its PR #25001 closed unmerged; none about 
> the margin); GitHub pull requests "servicebus lock renew" (#24511 merged, 
> #25001 closed unmerged, sessions).
> _Filed with Claude Code on behalf of allthingssecurity._



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to