resilience4j / resilience4j

Resilience4j is a fault tolerance library designed for Java8 and functional programming
Apache License 2.0
9.81k stars 1.35k forks source link

Timelimiter's TimeoutException is not considered as a failure to OPEN the CircuitBreaker #2013

Open tushar-meesho opened 1 year ago

tushar-meesho commented 1 year ago

Resilience4j version:

<artifactId>resilience4j-spring-boot2</artifactId>
 <version>1.7.0</version>

Java version: 17

I am using below code, and what I have seen is BulkheadFullException and RuntimeException is changing the state of circuitbreaker from CLOSED to OPEN, whereas that's not the case with TimeoutException.

@CircuitBreaker(name = "primary", fallbackMethod = "fallbackHandler")
@TimeLimiter(name = "primary")
@Bulkhead(name = "primary", type = Type.THREADPOOL)
public CompletableFuture<BatchGetRecordResponse> primaryHandler(String input) {
    return CompletableFuture.completedFuture(process(input));
}

public Object process(String input) {

    // TimeoutException will be thrown here by TimeLimiter as timeout is set to 10 seconds.
    try {
        Thread.sleep(15000);
    } catch (Exception e) {}

    return null;
}

public CompletableFuture<Object> fallbackHandler(String input, Exception e) {

    // 1. Timeout exception is being captured here, but it's does not open circuit breaker.
    // 2. BulkheadFullException is being captured here opens circuit breaker.
    // 3. Any RuntimeException which is captured here opens circuit breaker.

    log.error("primary fallback triggered. Error:", e);
    return CompletableFuture.completedFuture(null);
}

Q1. Even though there's only one fallback which is in circuit breaker, still TimeoutException's is not opening the CircuitBreaker, why this strange behaviour, and How to achieve this ?

tushar-meesho commented 1 year ago

The problem in your code is that your code is throwing an exception instead of returning a CompletableFurure which completed exceptionally. @RobWin Code is not really throwing an exception, exception is being thrown by TimeLimiter itself.

RobWin commented 1 year ago

Yes, I deleted the comment. I'm on vacation and answered too fast :)

vivek-sadineni commented 4 months ago

So, how are supposed to solve this issue. I am trying to solve the same thing, where Timeoutexception is not opening the r4j circuit

RobWin commented 4 months ago

Hi, did you try to debug it. Can you see why the TimeoutException is not recorded as a failure?