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)