
javaslang.circuitbreaker.CircuitBreaker Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of javaslang-circuitbreaker Show documentation
Show all versions of javaslang-circuitbreaker Show documentation
A CircuitBreaker pattern implementation for Java8 and functional programming .
/*
*
* Copyright 2015 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 javaslang.circuitbreaker;
import javaslang.control.Try;
import java.util.function.Function;
import java.util.function.Supplier;
/**
* A CircuitBreaker manages the state of a backend system. It is notified on the result of all
* attempts to communicate with the backend, via the {@link #recordSuccess} and {@link #recordFailure} methods.
* Before communicating with the backend, the respective connector must obtain the permission to do so via the method
* {@link #isCallPermitted()}.
*/
public interface CircuitBreaker {
/**
* Requests permission to call this circuitBreaker's backend.
*
* @return boolean whether a call should be permitted
*/
boolean isCallPermitted();
/**
* Records a failed call.
* This method must be invoked after a failed call.
*
* @param throwable The throwable which must be recorded
*/
void recordFailure(Throwable throwable);
/**
* Records a successful call.
* This method must be invoked after a successful call.
*/
void recordSuccess();
/**
* Get the name of this CircuitBreaker
*
* @return the name of this CircuitBreaker
*/
String getName();
/**
* Get the state of this CircuitBreaker
*
* @return the state of this CircuitBreaker
*/
State getState();
/**
* Get the CircuitBreakerConfig of this CircuitBreaker.
*
* @return the CircuitBreakerConfig of this CircuitBreaker
*/
CircuitBreakerConfig getCircuitBreakerConfig();
/**
* Get the Metrics of this CircuitBreaker.
*
* @return the Metrics of this CircuitBreaker
*/
Metrics getMetrics();
/**
* States of the CircuitBreaker state machine.
*/
enum State {
/** A CLOSED breaker is operating normally and allowing
requests through. */
CLOSED,
/** An OPEN breaker has tripped and will not allow requests
through. */
OPEN,
/** A HALF_OPEN breaker has completed its wait interval
and will allow requests */
HALF_OPEN
}
/**
* State transitions of the CircuitBreaker state machine.
*/
enum StateTransition {
CLOSED_TO_OPEN(State.CLOSED, State.OPEN),
HALF_OPEN_TO_CLOSED(State.HALF_OPEN, State.CLOSED),
HALF_OPEN_TO_OPEN(State.HALF_OPEN, State.OPEN),
OPEN_TO_HALF_OPEN(State.OPEN, State.HALF_OPEN);
State fromState;
State toState;
StateTransition(State fromState, State toState) {
this.fromState = fromState;
this.toState = toState;
}
public State getFromState() {
return fromState;
}
public State getToState() {
return toState;
}
@Override
public String toString(){
return String.format("State transition from %s to %s", fromState, toState);
}
}
interface Metrics {
/**
* Returns the failure rate in percentage. If the number of measured calls is below the minimum number of measured calls,
* it returns -1.
*
* @return the failure rate in percentage
*/
float getFailureRate();
/**
* Returns the current number of buffered calls.
*
* @return he current number of buffered calls
*/
int getNumberOfBufferedCalls();
/**
* Returns the current number of failed calls.
*
* @return the current number of failed calls.
*/
int getNumberOfFailedCalls();
}
/**
* Creates a supplier which is secured by a CircuitBreaker.
*
* @param supplier the original supplier
* @param circuitBreaker the CircuitBreaker
* @return a supplier which is secured by a CircuitBreaker.
*/
static Try.CheckedSupplier decorateCheckedSupplier(Try.CheckedSupplier supplier, CircuitBreaker circuitBreaker){
return () -> {
CircuitBreakerUtils.isCallPermitted(circuitBreaker);
try {
T returnValue = supplier.get();
circuitBreaker.recordSuccess();
return returnValue;
} catch (Throwable throwable) {
circuitBreaker.recordFailure(throwable);
throw throwable;
}
};
}
/**
* Creates a runnable which is secured by a CircuitBreaker.
*
* @param runnable the original runnable
* @param circuitBreaker the CircuitBreaker
* @return a runnable which is secured by a CircuitBreaker.
*/
static Try.CheckedRunnable decorateCheckedRunnable(Try.CheckedRunnable runnable, CircuitBreaker circuitBreaker){
return () -> {
CircuitBreakerUtils.isCallPermitted(circuitBreaker);
try{
runnable.run();
circuitBreaker.recordSuccess();
} catch (Throwable throwable){
circuitBreaker.recordFailure(throwable);
throw throwable;
}
};
}
/**
* Creates a supplier which is secured by a CircuitBreaker.
*
* @param supplier the original supplier
* @param circuitBreaker the CircuitBreaker
* @return a supplier which is secured by a CircuitBreaker.
*/
static Supplier decorateSupplier(Supplier supplier, CircuitBreaker circuitBreaker){
return () -> {
CircuitBreakerUtils.isCallPermitted(circuitBreaker);
try {
T returnValue = supplier.get();
circuitBreaker.recordSuccess();
return returnValue;
} catch (Throwable throwable) {
circuitBreaker.recordFailure(throwable);
throw throwable;
}
};
}
/**
* Creates a runnable which is secured by a CircuitBreaker.
*
* @param runnable the original runnable
* @param circuitBreaker the CircuitBreaker
* @return a runnable which is secured by a CircuitBreaker.
*/
static Runnable decorateRunnable(Runnable runnable, CircuitBreaker circuitBreaker){
return () -> {
CircuitBreakerUtils.isCallPermitted(circuitBreaker);
try{
runnable.run();
circuitBreaker.recordSuccess();
} catch (Throwable throwable){
circuitBreaker.recordFailure(throwable);
throw throwable;
}
};
}
/**
* Creates a function which is secured by a CircuitBreaker.
*
* @param function the original function
* @param circuitBreaker the CircuitBreaker
* @return a function which is secured by a CircuitBreaker.
*/
static Function decorateFunction(Function function, CircuitBreaker circuitBreaker){
return (T t) -> {
CircuitBreakerUtils.isCallPermitted(circuitBreaker);
try{
R returnValue = function.apply(t);
circuitBreaker.recordSuccess();
return returnValue;
} catch (Throwable throwable){
circuitBreaker.recordFailure(throwable);
throw throwable;
}
};
}
/**
* Creates a function which is secured by a CircuitBreaker.
*
* @param function the original function
* @param circuitBreaker the CircuitBreaker
* @return a function which is secured by a CircuitBreaker.
*/
static Try.CheckedFunction decorateCheckedFunction(Try.CheckedFunction function, CircuitBreaker circuitBreaker){
return (T t) -> {
CircuitBreakerUtils.isCallPermitted(circuitBreaker);
try{
R returnValue = function.apply(t);
circuitBreaker.recordSuccess();
return returnValue;
} catch (Throwable throwable){
circuitBreaker.recordFailure(throwable);
throw throwable;
}
};
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy