Claus Ibsen created CAMEL-24209:
-----------------------------------

             Summary: Circuit Breaker EIP - true async processing with 
CompletionStage decorators
                 Key: CAMEL-24209
                 URL: https://issues.apache.org/jira/browse/CAMEL-24209
             Project: Camel
          Issue Type: Improvement
          Components: eip
            Reporter: Claus Ibsen


The resilience4j Circuit Breaker processor (ResilienceProcessor) implements the 
async contract but is fully blocking: it always does callback.done(true); 
return true, and the timeout path parks the calling thread on future.get() 
while a second thread runs the work (two threads per in-flight message).

Resilience4j 2.x provides CompletionStage-based decorators for all three guards:
* CircuitBreaker.decorateCompletionStage() - fully non-blocking
* TimeLimiter.decorateCompletionStage(scheduler, supplier) - needs 
ScheduledExecutorService
* Bulkhead.decorateCompletionStage() - non-blocking permit acquire/release

Using these would allow completing the AsyncCallback from the worker thread, 
freeing consumer threads - the scenario the EIP exists for.

h3. Key challenges

# *Exchange copy lifecycle* - processTask() creates a correlated copy, 
UnitOfWork, processes, copies results, and releases in a try/finally. In async 
mode these must move into callback chains. Missed paths cause silent leaks.
# *Timeout race condition* - The AtomicBoolean exchangeWriteGuard prevents the 
worker from writing results after timeout triggers fallback. With both sides 
async, the race window widens.
# *Fallback restructuring* - CircuitBreakerFallbackTask implements 
Function<Throwable, Exchange> for synchronous recovery. As a CompletionStage 
error handler it returns a stage, not a value - the whole chain shape changes.
# *ScheduledExecutorService* - TimeLimiter.decorateCompletionStage() requires a 
ScheduledExecutorService, not the plain ExecutorService currently configured. 
Minor breaking change for users who pass a custom timeoutExecutorService bean.
# *Pooled task lifecycle* - acquire()/release() must move from try/finally to 
completion callbacks.

h3. Value

Under high concurrency with timeout enabled, thread consumption drops from 2 
blocked threads per exchange to 0. Most valuable for routes using async-capable 
components (Netty HTTP, Kafka) where the framework can be fully non-blocking 
end-to-end.

h3. Scope estimate

~300 lines production code (mostly ResilienceProcessor.java), ~20 lines in 
ResilienceReifier.java, plus ~100-150 lines of new async-specific tests. 
Medium-high risk due to exchange lifecycle and race condition handling.

See also umbrella issue CAMEL-24137 (Z2).

_Filed by Claude Code on behalf of davsclaus_



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to