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)

Reply via email to