io.github.resilience4j.circuitbreaker.operator.DisposableCircuitBreaker Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of resilience4j-rxjava2 Show documentation
Show all versions of resilience4j-rxjava2 Show documentation
Resilience4j is a lightweight, easy-to-use fault tolerance library designed for Java8 and functional programming
package io.github.resilience4j.circuitbreaker.operator;
import static java.util.Objects.requireNonNull;
import java.util.concurrent.atomic.AtomicReference;
import io.github.resilience4j.adapter.Permit;
import io.github.resilience4j.circuitbreaker.CircuitBreaker;
import io.github.resilience4j.circuitbreaker.CircuitBreakerOpenException;
import io.github.resilience4j.core.StopWatch;
import io.reactivex.disposables.Disposable;
import io.reactivex.internal.disposables.DisposableHelper;
/**
* A disposable circuit-breaker.
*
* @param the type of the emitted event
*/
class DisposableCircuitBreaker extends AtomicReference implements Disposable {
private final CircuitBreaker circuitBreaker;
private StopWatch stopWatch;
private final AtomicReference permitted = new AtomicReference<>(Permit.PENDING);
DisposableCircuitBreaker(CircuitBreaker circuitBreaker) {
this.circuitBreaker = requireNonNull(circuitBreaker);
}
@Override
public final void dispose() {
DisposableHelper.dispose(this);
}
@Override
public final boolean isDisposed() {
return DisposableHelper.isDisposed(get());
}
/**
* onSuccess ensured to be called only when safe.
*
* @param disposable the disposable
*/
protected void onSubscribeInner(Disposable disposable) {
//Override when needed.
}
protected final void onSubscribeWithPermit(Disposable disposable) {
if (DisposableHelper.setOnce(this, disposable)) {
if (acquireCallPermit()) {
onSubscribeInner(this);
} else {
dispose();
onSubscribeInner(this);
permittedOnError(circuitBreakerOpenException());
}
}
}
/**
* onError ensured to be called only when permitted.
*
* @param e the error
*/
protected void permittedOnError(Throwable e) {
//Override when needed.
}
protected final void onErrorInner(Throwable e) {
markFailure(e);
if (isInvocationPermitted()) {
permittedOnError(e);
}
}
/**
* onComplete ensured to be called only when permitted.
*/
protected void permittedOnComplete() {
//Override when needed.
}
protected final void onCompleteInner() {
markSuccess();
if (isInvocationPermitted()) {
permittedOnComplete();
}
}
/**
* onSuccess ensured to be called only when permitted.
*
* @param value the value
*/
protected void permittedOnSuccess(T value) {
//Override when needed.
}
protected final void onSuccessInner(T value) {
markSuccess();
if (isInvocationPermitted()) {
permittedOnSuccess(value);
}
}
/**
* onNext ensured to be called only when permitted.
*
* @param value the value
*/
protected void permittedOnNext(T value) {
//Override when needed.
}
protected final void onNextInner(T value) {
if (isInvocationPermitted()) {
permittedOnNext(value);
}
}
private boolean acquireCallPermit() {
boolean callPermitted = false;
if (permitted.compareAndSet(Permit.PENDING, Permit.ACQUIRED)) {
callPermitted = circuitBreaker.isCallPermitted();
if (!callPermitted) {
permitted.set(Permit.REJECTED);
} else {
stopWatch = StopWatch.start(circuitBreaker.getName());
}
}
return callPermitted;
}
private boolean isInvocationPermitted() {
return !isDisposed() && wasCallPermitted();
}
private Exception circuitBreakerOpenException() {
return new CircuitBreakerOpenException(String.format("CircuitBreaker '%s' is open", circuitBreaker.getName()));
}
private void markFailure(Throwable e) {
if (wasCallPermitted()) {
circuitBreaker.onError(stopWatch.stop().getProcessingDuration().toNanos(), e);
}
}
private void markSuccess() {
if (wasCallPermitted()) {
circuitBreaker.onSuccess(stopWatch.stop().getProcessingDuration().toNanos());
}
}
private boolean wasCallPermitted() {
return permitted.get() == Permit.ACQUIRED;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy