question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

@TimeLimiter times out slow method but does not cancel running future

See original GitHub issue

Resilience4j version: 1.3.1

Java version: 1.8.0_241

Spring Boot version: 2.2.5.RELEASE

If a method has the @TimeLimiter annotation added that references a time limiter configured with cancelRunningFuture: true then, when a timeout event successfully occurs, the currently running CompleteableFuture does not appear to be cancelled. Instead it just keeps on running.

In the below set up the slow method being called from the protected method just sleeps for 30 seconds and then writes a message to announce it has woken up. This is deliberately being done to try and simulate a very slow/hung method.

application.yml


  resilience4j:
    instances:
      mytimelimiter:
        baseConfig: default
        timeoutDuration: 5000
        cancelRunningFuture: true

    thread-pool-bulkhead:
      instances:
        mybulkhead:
          coreThreadPoolSize: 10
          maxThreadPoolSize: 10
          queueCapacity: 5

SlowService.java


@Service
public class SlowService {

    public String slowMethod() {
        LOGGER.info("slowMethod going to sleep for 30 seconds...");
        try {
            Thread.sleep(30000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        LOGGER.info("...slowMethod awake after 30 seconds");

        . . .

        return "Successful call to slowMethod";
    }
}

MyController.java


@RestController
public class MyController {

    . . .

    @Autowired
    private final SlowService slowService;

    . . .

    @Bulkhead(name = "mybulkhead", type = Type.THREADPOOL)
    @TimeLimiter(name = "mytimelimiter")
    @GetMapping("/slow")
    public CompletableFuture<String> slowHandler() {
        return CompletableFuture.supplyAsync(slowService::slowMethod);
    }

The presence of the @TimeLimiter annotation on the slowHandler() method above ensures that requests to it time out after 5000ms (just as configured for the mytimelimiter instance in the application.yml values). Perfect. However, after another 25 seconds or so the slowMethod() logs that it has woken up and then can presumably carry on going about its work. That seems to indicate that the future was not cancelled when the time out successfully occurred on the calling method.

Is the above working as expected? Perhaps it is the case that resilience4j.timelimiter.instances.{name}.cancelRunningFuture is not expected to have any effect when the time limiter is referenced from a @TimeLimiter annotation? Alternatively, maybe my calling method decorated with the annotation needs to be rewritten in order to enable the cancelling of the CompleteableFuture?

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Comments:15 (7 by maintainers)

github_iconTop GitHub Comments

1reaction
RobWincommented, Dec 2, 2020

No, TimeLimiter (TimeLimiterAspect) still throws a TimeoutException. See our Spring Boot 2 demo. But TimeLimiter cannot cancel a CompletableFuture. Otherwise we would have to implement our own CompletableFuture, but that is too cumbersome to maintain.

The TimeLimiter also works for all reactive types from Spring Reactor or RxJava2 and RxJava3

1reaction
SidekickJohncommented, Dec 2, 2020

@RobWin I’m trying to understand this, but I struggle with the following:

  • I tried the @TimeLimiter-Annotation on a method simply returning an object/String/whatever --> I get an error that the TimeLimiter-Annotation needs a future return type --> fine with me

  • on the other hand you mention, that the @TimeLimiter-Annotation cannot cancel running CompletableFutures and therefore doesn’t work as expected

So what return-type do I need for the @TimeLimiter-Annotation to work as expected (cancel running execution and throw TimeoutException)?

We had a running functional implementation, but we are trying to switch away from this to an annotation-based style. Simply because we want to get rid of the gluecode (decorating suppliers…).

Read more comments on GitHub >

github_iconTop Results From Across the Web

TimeLimiter times out slow method but does not cancel ...
That seems to indicate that the future was not cancelled when the time out successfully occurred on the calling method. Is the above...
Read more >
Timelimiter is not interrupting the thread - java - Stack Overflow
TimeLimiter cannot cancel a CompletableFuture. See @TimeLimiter times out slow method but does not cancel running future #905 Points out, ...
Read more >
TimeLimiter - resilience4j
You can use the builder to configure: the timeout duration; whether cancel should be called on the running future. Java. TimeLimiterConfig ...
Read more >
Resilience4j Session-8 limit the amount of time spent calling a ...
In this tutorial we are going to learn how to limit the amount of time spent calling a remote service using Resilience4j TimeLimiter...
Read more >
Use Resilience4j framework to implement asynchronous ...
This configuration is only applies to Future not apply to CompletableFuture. When the timeout occurs, it will cancel the running ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found