shashank created CAMEL-26422:
--------------------------------

             Summary: camel-core - Circuit Breaker EIP (camel-resilience4j, 
camel-microprofile-fault-tolerance) inside a doTry ends the doTry for the steps 
after it: a later failure is not caught by the doCatch
                 Key: CAMEL-26422
                 URL: https://issues.apache.org/jira/browse/CAMEL-26422
             Project: Camel
          Issue Type: Bug
          Components: camel-core, camel-microprofile-fault-tolerance
            Reporter: shashank
            Assignee: shashank


A circuit breaker runs its steps as if in a doTry: it sets the exchange 
property {{TryRouteBlock}} while they run. When the circuit breaker is itself 
in the steps of a {{doTry}} (main 017f4fd11c4a, Resilience4j sync and async, 
MicroProfile Fault Tolerance):

* a fallback that recovered from a failure sets {{CamelExceptionHandled}} (as a 
doCatch does) and leaves it set. {{CatchProcessor}} skips its clause when that 
property is set, so no doCatch of the enclosing doTry catches a later failure 
in the same doTry, whatever the failing step is: the failure is thrown from the 
doTry;
* when the circuit breaker is done it removes {{TryRouteBlock}} instead of 
restoring the value of the enclosing doTry. A later routing slip, dynamic 
router, multicast or recipient list of the same doTry then wraps its outputs in 
the route's error handler, so its failure is redelivered and goes to the dead 
letter channel instead of the doCatch.

{code:java}
from("direct:start").doTry()
    .circuitBreaker().throwException(new IllegalArgumentException("Recover me"))
        .onFallback().setBody(constant("Recovered")).end()
    .throwException(new IllegalStateException("later failure"))
    .doCatch(IllegalStateException.class).to("mock:caught").end();
// expected: mock:caught gets the exchange; actual: nothing, the exchange fails 
with the IllegalStateException
{code}

CAMEL-25114 lists the circuit breakers removing the marker under "Not changed"; 
the PR of CAMEL-26332 names the fallback's {{CamelExceptionHandled}} as a 
follow-up. The code is older than CAMEL-25115 (4.22 does the same).

*Fix* (proposed): both circuit breaker processors keep the values of 
{{TryRouteBlock}} and {{CamelExceptionHandled}} of the enclosing scope when 
they start and set them again when they are done, as {{TryProcessor}} does for 
a nested doTry (Resilience4j in the callback, so also when it completes 
asynchronously). Upgrade guide entry: such failures now go to the doCatch; to 
have those steps use the route's error handler, move them out of the doTry.

*Tests*: {{ResilienceOuterTryScopeTest}} (6 tests) and 
{{FaultToleranceOuterTryScopeTest}} (5 tests): a recipient list after a circuit 
breaker (also asynchronous), a recipient list and a plain failing step after a 
recovered fallback, and two controls (a circuit breaker inside a doCatch, a 
circuit breaker outside a doTry). 7 fail on main and pass with the fix.

_Filed with Claude Code on behalf of allthingssecurity._



--
This message was sent by Atlassian Jira
(v10.3.26#10030026)

Reply via email to