/*
*
* Copyright 2016 Robert Winkler
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*
*/
package io.github.resilience4j.circuitbreaker;
import java.time.Duration;
import java.util.function.Predicate;
/**
* A {@link CircuitBreakerConfig} configures a {@link CircuitBreaker}
*/
public class CircuitBreakerConfig {
public static final int DEFAULT_MAX_FAILURE_THRESHOLD = 50; // Percentage
public static final int DEFAULT_WAIT_DURATION_IN_OPEN_STATE = 60; // Seconds
public static final int DEFAULT_RING_BUFFER_SIZE_IN_HALF_OPEN_STATE = 10;
public static final int DEFAULT_RING_BUFFER_SIZE_IN_CLOSED_STATE = 100;
private float failureRateThreshold = DEFAULT_MAX_FAILURE_THRESHOLD;
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);
// The default exception predicate counts all exceptions as failures.
private Predicate<? super Throwable> recordFailurePredicate = (exception) -> true;
private CircuitBreakerConfig(){
}
public float getFailureRateThreshold() {
return failureRateThreshold;
}
public Duration getWaitDurationInOpenState() {
return waitDurationInOpenState;
}
public int getRingBufferSizeInHalfOpenState() {
return ringBufferSizeInHalfOpenState;
}
public int getRingBufferSizeInClosedState() {
return ringBufferSizeInClosedState;
}
public Predicate<? super Throwable> getRecordFailurePredicate() {
return recordFailurePredicate;
}
/**
* Returns a builder to create a custom CircuitBreakerConfig.
*
* @return a {@link Builder}
*/
public static Builder custom(){
return new Builder();
}
/**
* Creates a default CircuitBreaker configuration.
*
* @return a default CircuitBreaker configuration.
*/
public static CircuitBreakerConfig ofDefaults(){
return new Builder().build();
}
public static class Builder {
private CircuitBreakerConfig config = new CircuitBreakerConfig();
/**
* Configures the failure rate threshold in percentage above which the CircuitBreaker should trip open and start short-circuiting calls.
*
* The threshold must be between 1 and 100. Default value is 50 percentage.
*
* @param failureRateThreshold the failure rate threshold in percentage
* @return the CircuitBreakerConfig.Builder
*/
public Builder failureRateThreshold(int failureRateThreshold) {
if (failureRateThreshold < 1 || failureRateThreshold > 100) {
throw new IllegalArgumentException("failureRateThreshold must be between 1 and 100");
}
config.failureRateThreshold = failureRateThreshold;
return this;
}
/**
* Configures the wait duration which specifies how long the CircuitBreaker should stay open, before it switches to half open.
* Default value is 60 seconds.
*
* @param waitDurationInOpenState the wait duration which specifies how long the CircuitBreaker should stay open
* @return the CircuitBreakerConfig.Builder
*/
public Builder waitDurationInOpenState(Duration waitDurationInOpenState) {
if (waitDurationInOpenState.getSeconds() < 1) {
throw new IllegalArgumentException("waitDurationInOpenState must be at least 1000[ms]");
}
config.waitDurationInOpenState = waitDurationInOpenState;
return this;
}
/**
* Configures the size of the ring buffer when the CircuitBreaker is half open. The CircuitBreaker stores the success/failure success / failure status of the latest calls in a ring buffer.
* For example, if {@code ringBufferSizeInClosedState} is 10, then at least 10 calls must be evaluated, before the failure rate can be calculated.
* If only 9 calls have been evaluated the CircuitBreaker will not trip back to closed or open even if all 9 calls have failed.
*
* The size must be greater than 0. Default size is 10.
*
* @param ringBufferSizeInHalfOpenState the size of the ring buffer when the CircuitBreaker is is half open
* @return the CircuitBreakerConfig.Builder
*/
public Builder ringBufferSizeInHalfOpenState(int ringBufferSizeInHalfOpenState) {
if (ringBufferSizeInHalfOpenState < 1 ) {
throw new IllegalArgumentException("ringBufferSizeInHalfOpenState must be greater than 0");
}
config.ringBufferSizeInHalfOpenState = ringBufferSizeInHalfOpenState;
return this;
}
/**
* Configures the size of the ring buffer when the CircuitBreaker is closed. The CircuitBreaker stores the success/failure success / failure status of the latest calls in a ring buffer.
* For example, if {@code ringBufferSizeInClosedState} is 100, then at least 100 calls must be evaluated, before the failure rate can be calculated.
* If only 99 calls have been evaluated the CircuitBreaker will not trip open even if all 99 calls have failed.
*
* The size must be greater than 0. Default size is 100.
*
* @param ringBufferSizeInClosedState the size of the ring buffer when the CircuitBreaker is closed.
* @return the CircuitBreakerConfig.Builder
*/
public Builder ringBufferSizeInClosedState(int ringBufferSizeInClosedState) {
if (ringBufferSizeInClosedState < 1) {
throw new IllegalArgumentException("ringBufferSizeInClosedState must be greater than 0");
}
config.ringBufferSizeInClosedState = ringBufferSizeInClosedState;
return this;
}
/**
* Configures a Predicate which evaluates if an exception should be recorded as a failure and thus increase the failure rate.
* The Predicate must return true if the exception should count as a failure, otherwise it must return false.
*
* @param predicate the Predicate which evaluates if an exception should be recorded as a failure and thus trigger the CircuitBreaker
* @return the CircuitBreakerConfig.Builder
*/
public Builder recordFailure(Predicate<? super Throwable> predicate) {
config.recordFailurePredicate = predicate;
return this;
}
/**
* Builds a CircuitBreakerConfig
*
* @return the CircuitBreakerConfig
*/
public CircuitBreakerConfig build() {
return config;
}
}
}