You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@camel.apache.org by "shashank (Jira)" <ji...@apache.org> on 2026/09/23 11:51:00 UTC
[jira] [Created] (CAMEL-24926) throttle(n).concurrentRequestsMode() lets more than n exchanges in when one of them takes longer than 10 seconds
shashank created CAMEL-24926:
--------------------------------
Summary: throttle(n).concurrentRequestsMode() lets more than n exchanges in when one of them takes longer than 10 seconds
Key: CAMEL-24926
URL: https://issues.apache.org/jira/browse/CAMEL-24926
Project: Camel
Issue Type: Bug
Components: camel-core
Reporter: shashank
With {{throttle(1).concurrentRequestsMode()}}, two exchanges can be inside the throttled part of the route at the same time:
# Exchange X passes the throttle and completes. Returning its permit schedules a cleanup of the throttler state 10 seconds later.
# Exchange A takes the permit and runs for 15 seconds.
# The cleanup runs while A is still being processed and removes the state (the semaphore).
# Exchange B arrives. There is no state for the key anymore, so a new one with all permits is created, and B passes the throttle while A still holds its permit.
Observed with a route whose processor sleeps for slow messages:
{noformat}
t= 0.25s enter X (inside: 1)
t= 0.26s leave X
t= 0.77s enter A (inside: 1)
t=11.28s enter B (inside: 2)
t=12.28s leave B
t=15.78s leave A
max concurrent exchanges inside throttle(1).concurrentRequestsMode() = 2 (expected 1)
{noformat}
Any exchange that holds a permit for longer than 10 seconds after the previous permit was returned breaks the limit, which is a typical case for this mode (a slow backend that only accepts n connections).
Cause: {{ConcurrentRequestsThrottler.ThrottlingState.release()}} schedules {{clean()}} after {{CLEAN_PERIOD}} (10 s), and {{clean()}} calls {{states.remove(key)}} without checking whether a permit was taken in the meantime. Taking a permit does not cancel the scheduled cleanup.
Proposed fix: only remove the state in {{clean()}} when all permits are available and nobody is waiting for one. To close the remaining window where an exchange has looked up the state just before it was removed, mark the state as removed (under the state lock), and have an exchange that took a permit from a removed state give it back and take one from the current state instead.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)