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.

Problem with circuit breaker in asynch mode

See original GitHub issue

Hi all.

I have some problems regarding the transition from half_open to close state when using asynch mode (using version 0.15.0). Here is my code

CircuitBreakerConfig circuitBreakerConfig =
                CircuitBreakerConfig.custom()
                        .failureRateThreshold(50.0F)
                        .waitDurationInOpenState(Duration.ofMillis(1 * 30 * 1000))
                        .ringBufferSizeInHalfOpenState(2)
                        .ringBufferSizeInClosedState(3) 
                        .ignoreExceptions(BusinessException.class)
                        .build();
CircuitBreakerRegistry circuitBreakerRegistry = CircuitBreakerRegistry.of(circuitBreakerConfig);
circuitBreaker = circuitBreakerRegistry.circuitBreaker("circuit breaker", circuitBreakerConfig);
circuitBreaker.getEventPublisher()
                .onStateTransition(event -> {
                    System.out.println("CIRCUIT BREAKER " + event.getStateTransition().toString());
                });
public void doRun(long messageID) {
        System.out.println("CIRCUIT BREAKER IS " + circuitBreaker.getState());
        Supplier<CompletionStage<Void>> completionStageSupplier = () ->  CompletableFuture.supplyAsync(() -> {
            try {
                return service.execute(messageID);
            } catch (Exception e) {
                throw new CompletionException(e);
            }
        });

        CompletionStage<Void> completionStage = Decorators.ofCompletionStage(completionStageSupplier)
                //  .withRetry(retry, Executors.newSingleThreadScheduledExecutor())
                .withCircuitBreaker(circuitBreaker)
                .get();
   try {
            Try.ofSupplier(() -> completionStage.toCompletableFuture()).recover(throwable -> {
                CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
                    recovery(throwable);
                });
                return future;

            }).get().get(30, TimeUnit.SECONDS);
        } catch (Exception e) {
            System.out.println("try exception " + e);
        }
}

Here is my scenario: My application sends a message every 10 seconds, so that the method doRun(messageID) get called for each new message. The service , in a first time, returns no exception, so that the circuit is CLOSED.

[x] Sent '{"id":1,"message":"order"}
CIRCUIT BREAKER IS CLOSED
response is pong 1 ( _here the response of the service called_) 

Now, i disable the service so that it returns an exception.

CIRCUIT BREAKER State transition from CLOSED to OPEN
[x] Sent '{"id":10,"message":"order"}
CIRCUIT BREAKER IS OPEN
try exception java.util.concurrent.ExecutionException: io.github.resilience4j.circuitbreaker.CallNotPermittedException: CircuitBreaker 'circuit breaker' is OPEN and does not permit further calls

So far so good. Then, i restablish the service. After the delay , the state goes to HALF_OPEN as expected

[x] Sent '{"id":13,"message":"order"}
CIRCUIT BREAKER IS HALF_OPEN
response is pong 13
[x] Sent '{"id":14,"message":"order"}
CIRCUIT BREAKER IS HALF_OPEN
response is pong 14

Still good. But after these 2 tries, i expect the circuit breaker to go to the CLOSED state after the next message. But here is the result:

[x] Sent '{"id":16,"message":"order"}
CIRCUIT BREAKER IS HALF_OPEN
try exception java.util.concurrent.ExecutionException: io.github.resilience4j.circuitbreaker.CallNotPermittedException: CircuitBreaker 'circuit breaker' is HALF_OPEN and does not permit further calls

By teh way, is there something wrong with my call to recovery method ? it’s never called…

I have no problem in synch mode with this code:

       CheckedFunction0<Void> checkedSupplier = Retry.decorateCheckedSupplier(retry, () -> service.execute(messageID));
        checkedSupplier = CircuitBreaker.decorateCheckedSupplier(circuitBreaker, checkedSupplier);


        Try.of(checkedSupplier)
                .recover(this::recovery).get();

Thanks for your help!

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Comments:11 (8 by maintainers)

github_iconTop GitHub Comments

2reactions
RobWincommented, Jun 7, 2019

Is it possible at the time being to decorate a timelimiter in async mode ?

Currently a TimeLimiter can only decorate a Future<T> or CompletableFuture<T> and converts it into a Callable<T>. You can’t use it to decorate a CompletionStage.

But you could do the following:

Supplier<CompletionStage<String>> completionStageSupplier =
                () -> CompletableFuture.supplyAsync(helloWorldService::returnHelloWorld);

Supplier<CompletionStage<String>> decoratedCompletionStage = Decorators.ofCompletionStage(completionStageSupplier)
                .withCircuitBreaker(circuitBreaker)
                .withRetry(Retry.ofDefaults("id"), Executors.newSingleThreadScheduledExecutor())
                .withBulkhead(Bulkhead.ofDefaults("testName"))
                .decorate();

TimeLimiter timeLimiter = TimeLimiter.ofDefaults();
Callable<String> result = TimeLimiter
    .decorateFutureSupplier(timeLimiter, () -> decoratedCompletionStage.get().toCompletableFuture());
0reactions
RobWincommented, Jun 7, 2019
Read more comments on GitHub >

github_iconTop Results From Across the Web

Is circuit breaker pattern applicable for asynchronous requests ...
The Circuit Breaker Pattern is mostly applicable for synchronous service communication. It is meant to avoid that a service is becoming ...
Read more >
The Circuit Breaker Pattern - Dos and Don'ts - AKF Partners
The circuit breaker pattern proxies or encapsulates service A making a call to remote service or resource B. When error rates or response ......
Read more >
CircuitBreaker - Martin Fowler
The example I've shown is a circuit breaker for synchronous calls, but circuit breakers are also useful for asynchronous communications. A ...
Read more >
Circuit Breaker Pattern - How to build a better Microservice ...
An opossum is a Node.js circuit breaker that executes asynchronous functions and monitors their execution status. When things start failing, ...
Read more >
Design patterns: Circuit Breaker - Bartosz Sypytkowski
First, Circuit Breaker defines a safe time delay given to the action to respond. Service which won't fit specified timeout is considered to...
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