shashank created CAMEL-25014:
--------------------------------
Summary: ThrottlingExceptionRoutePolicy: since CAMEL-24903 the
circuit stays open forever when the halfOpenHandler is not ready once, and
keepOpen no longer suspends the consumer after a route restart
Key: CAMEL-25014
URL: https://issues.apache.org/jira/browse/CAMEL-25014
Project: Camel
Issue Type: Bug
Components: camel-core
Reporter: shashank
CAMEL-24903 (commit bd4d2ba20, PR #26799) added an early return to
{{ThrottlingExceptionRoutePolicy.openCircuit}}
({{ThrottlingExceptionRoutePolicy.java:308-313}}):
{code:java}
if (state.get() == STATE_OPEN) {
return;
}
{code}
so that {{setKeepOpen(true)}} can call {{openCircuit}} safely. Two existing
callers rely on {{openCircuit}} doing its work while the circuit is already
OPEN:
# {{calculateState}}, OPEN branch with a {{ThrottlingExceptionHalfOpenHandler}}
({{:273-280}}): when the handler says "not ready", {{openCircuit}} is called to
re-arm the half-open timer. Now it returns at once: no timer is scheduled, the
consumer stays suspended, so no exchange completes and {{calculateState}} is
never called again. The first "not ready" answer suspends the route forever,
although the handler is exactly meant to be asked again later.
# {{onStart}} with {{keepOpen=true}} ({{:177-181}}): the policy is a
CamelContext service, so its state survives {{stopRoute}}/{{startRoute}}. After
a restart the state is still OPEN, {{openCircuit}} returns before suspending
the newly started consumer, and the route consumes although keepOpen is set.
*Reproduction* (file consumer, {{new ThrottlingExceptionRoutePolicy(1, 60000,
500, null)}}; the control runs use the class from before bd4d2ba20):
{noformat}
handler (halfOpenHandler: false on the 1st call, true afterwards; one failing
file, then 3 good files)
main: 3 s later: handlerCalls=1 circuit=opened consumer=Suspended
goodProcessed=0/3 (same after 6 s)
pre-24903: 3 s later: handlerCalls=2 circuit=closed consumer=Started
goodProcessed=3/3
keepopen (keepOpen=true; stopRoute + startRoute; 3 files dropped after the
restart)
main: circuit=opened consumer=Started consumed=3/3 (expected 0)
pre-24903: circuit=opened consumer=Suspended consumed=0/3
{noformat}
TLA+: {{tep_handler}} violates {{NoStuckOpen}} (circuit OPEN, consumer
suspended, no half-open timer, nothing inflight) in 4 states (Consume ->
Done(failure) -> TimerFire(handler not ready)), {{tep_handler_live}} violates
{{EventuallyClosed}}, {{tep_keepopen_restart}} violates {{KeepOpenHolds}}. The
same configurations with the code before bd4d2ba20 hold.
*Proposed fix:* keep the idempotent check in {{openCircuit}} (it was added in
the CAMEL-24903 review so concurrent callers cannot stack half open timers),
and add {{reopenCircuit}}, which suspends the consumer and schedules the next
half open check also when the circuit is already open. Use it in the two places
that must act on an open circuit: the half open handler "not ready" branch of
{{calculateState}}, and {{onStart}} with {{keepOpen}}. {{addHalfOpenTimer}}
replaces the previous timer under the lock and cancels it, and a half open task
cancels only its own timer, so re-opening never leaves more than one timer
thread.
#26799 is labelled {{port/camel-4.22.x}}, so the same regression will reach
4.22.x when it is ported; the fix should be ported with it.
_Filed with Claude Code on behalf of allthingssecurity._
--
This message was sent by Atlassian Jira
(v8.20.10#820010)