Skip to content

Commit

Permalink
Issue ReactiveX#197: Option to auto transition to half open (Reactive…
Browse files Browse the repository at this point in the history
…X#216)

* Issue ReactiveX#197: Option to auto transition to half open

* Issue ReactiveX#197: Option to auto transition, tidy up

* Issue ReactiveX#197: Option to auto transition, reduce number of cb instances

* Issue ReactiveX#197 Open to auto transition to half open, PR changes

* Issue ReactiveX#197 Open to auto transition to half open, PR changes 2

* Issue ReactiveX#197 tidy up config after rebase
  • Loading branch information
mattca authored and RobWin committed Mar 28, 2018
1 parent 774f7b0 commit 99f4eda
Show file tree
Hide file tree
Showing 4 changed files with 341 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ public class CircuitBreakerConfig {
private Duration waitDurationInOpenState = Duration.ofSeconds(DEFAULT_WAIT_DURATION_IN_OPEN_STATE);
// The default exception predicate counts all exceptions as failures.
private Predicate<Throwable> recordFailurePredicate = DEFAULT_RECORD_FAILURE_PREDICATE;
private boolean automaticTransitionFromOpenToHalfOpenEnabled = false;

private CircuitBreakerConfig(){
}
Expand All @@ -64,7 +65,11 @@ public int getRingBufferSizeInClosedState() {
public Predicate<Throwable> getRecordFailurePredicate() {
return recordFailurePredicate;
}


public boolean isAutomaticTransitionFromOpenToHalfOpenEnabled() {
return automaticTransitionFromOpenToHalfOpenEnabled;
}

/**
* Returns a builder to create a custom CircuitBreakerConfig.
*
Expand Down Expand Up @@ -94,6 +99,7 @@ public static class Builder {
private int ringBufferSizeInHalfOpenState = DEFAULT_RING_BUFFER_SIZE_IN_HALF_OPEN_STATE;
private int ringBufferSizeInClosedState = DEFAULT_RING_BUFFER_SIZE_IN_CLOSED_STATE;
private Duration waitDurationInOpenState = Duration.ofSeconds(DEFAULT_WAIT_DURATION_IN_OPEN_STATE);
private boolean automaticTransitionFromOpenToHalfOpenEnabled = false;

/**
* Configures the failure rate threshold in percentage above which the CircuitBreaker should trip open and start short-circuiting calls.
Expand Down Expand Up @@ -220,6 +226,16 @@ public final Builder ignoreExceptions(Class<? extends Throwable>... errorClasses
return this;
}

/**
* Enables automatic transition from OPEN to HALF_OPEN state once the waitDurationInOpenState has passed.
*
* @return the CircuitBreakerConfig.Builder
*/
public Builder enableAutomaticTransitionFromOpenToHalfOpen() {
this.automaticTransitionFromOpenToHalfOpenEnabled = true;
return this;
}

/**
* Builds a CircuitBreakerConfig
*
Expand All @@ -233,6 +249,7 @@ public CircuitBreakerConfig build() {
config.ringBufferSizeInClosedState = ringBufferSizeInClosedState;
config.ringBufferSizeInHalfOpenState = ringBufferSizeInHalfOpenState;
config.recordFailurePredicate = errorRecordingPredicate;
config.automaticTransitionFromOpenToHalfOpenEnabled = automaticTransitionFromOpenToHalfOpenEnabled;
return config;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package io.github.resilience4j.circuitbreaker.internal;

import io.vavr.Lazy;

import java.time.Duration;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
* Schedules tasks to be completed after a duration. E.g. to automatically transition from open to half open state
* when automaticTransitionFromOpenToHalfOpenEnabled config property is set to true.
*/
public class AutoTransitioner {

private static final Lazy<ScheduledExecutorService> executorService = Lazy.of(
Executors::newSingleThreadScheduledExecutor);

private AutoTransitioner() {
}

public static void scheduleAutoTransition(Runnable transition, Duration waitDurationInOpenState) {
executorService.get().schedule(
transition,
waitDurationInOpenState.toMillis(),
TimeUnit.MILLISECONDS);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

import io.github.resilience4j.circuitbreaker.CircuitBreaker;

import java.time.Duration;
import java.time.Instant;

final class OpenState extends CircuitBreakerState {
Expand All @@ -29,8 +30,13 @@ final class OpenState extends CircuitBreakerState {

OpenState(CircuitBreakerStateMachine stateMachine, CircuitBreakerMetrics circuitBreakerMetrics) {
super(stateMachine);
this.retryAfterWaitDuration = Instant.now().plus(stateMachine.getCircuitBreakerConfig().getWaitDurationInOpenState());
final Duration waitDurationInOpenState = stateMachine.getCircuitBreakerConfig().getWaitDurationInOpenState();
this.retryAfterWaitDuration = Instant.now().plus(waitDurationInOpenState);
this.circuitBreakerMetrics = circuitBreakerMetrics;

if (stateMachine.getCircuitBreakerConfig().isAutomaticTransitionFromOpenToHalfOpenEnabled()) {
AutoTransitioner.scheduleAutoTransition(stateMachine::transitionToHalfOpenState, waitDurationInOpenState);
}
}

/**
Expand Down
Loading

0 comments on commit 99f4eda

Please sign in to comment.