Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ThreadPoolBulkhead with TimeLimiter, seeing TimeoutExceptions #2103

Open
PureXYZ opened this issue Jan 29, 2024 · 1 comment
Open

ThreadPoolBulkhead with TimeLimiter, seeing TimeoutExceptions #2103

PureXYZ opened this issue Jan 29, 2024 · 1 comment

Comments

@PureXYZ
Copy link

PureXYZ commented Jan 29, 2024

Resilience4j version: 1.7.1

Java version: 8

*Also tried with 2.2.0 & Java 17

I am using ThreadPoolBulkhead with TimeLimiter, but unexpectedly seeing TimeoutExceptions.
It appears that the TimeLimiter starts counting when the function is "submitted", not when it actually starts execution.

My simplified example:

private <T> T execute() {
    try {
      CompletableFuture<T> future = Decorators.ofSupplier(() -> callApi(...))
          .withThreadPoolBulkhead(bulkhead)
          .withTimeLimiter(timeLimiter, scheduler)
          .get().toCompletableFuture();
      return future.get();
    } catch (...) {
      ...
    }
}

Here with configuration settings:

ThreadPoolBulkheadConfig:
maxThreadPoolSize=1
coreThreadPoolSize=1
queueCapacity=100
keepAliveDuration=Duration.ofMillis(20)

TimeLimiterConfig
timeoutDuration=Duration.ofMillis(45000)

callApi(...) in this example takes 5 seconds to respond.
I have confirmed it is not the api timing out, in fact in this experiment, I have just changed it to just do Thread.sleep(5000); to confirm.

In this situation, if execute is called 10 times at the same time (concurrently). Then I get TimeoutException.
My observation is that the bulkhead will let 1 call at a time, 5s each. Then on the 10th call, it will throw TimeoutException.
Even though each execution of callApi(...) only takes 5s.

Is this behaviour expected? My expectation was that the timeout was to apply to each execution of callApi(...)
i.e. TimeoutException is thrown if callApi(...) takes longer than 45s.

@ljluestc
Copy link


import io.github.resilience4j.timelimiter.TimeLimiter;

private <T> T execute() {
    try {
        Callable<T> callApiWithTimeout = TimeLimiter.decorateFutureSupplier(
            timeLimiter, 
            () -> callApi(...));
        
        CompletableFuture<T> future = CompletableFuture.supplyAsync(callApiWithTimeout);
        
        return future.get();
    } catch (...) {
        // Handle exceptions
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants