Search in sources :

Example 1 with CircuitBreakerOpenException

use of io.github.resilience4j.circuitbreaker.CircuitBreakerOpenException in project resilience4j by resilience4j.

the class CircuitBreakerTransformer method apply.

@Override
public Upstream<T> apply(Upstream<? extends T> upstream) throws Exception {
    return down -> {
        long start;
        if (circuitBreaker.isCallPermitted()) {
            start = System.nanoTime();
            upstream.connect(new Downstream<T>() {

                @Override
                public void success(T value) {
                    long durationInNanos = System.nanoTime() - start;
                    circuitBreaker.onSuccess(durationInNanos);
                    down.success(value);
                }

                @Override
                public void error(Throwable throwable) {
                    long durationInNanos = System.nanoTime() - start;
                    circuitBreaker.onError(durationInNanos, throwable);
                    try {
                        if (recoverer != null) {
                            down.success(recoverer.apply(throwable));
                        } else {
                            down.error(throwable);
                        }
                    } catch (Throwable t) {
                        down.error(t);
                    }
                }

                @Override
                public void complete() {
                    down.complete();
                }
            });
        } else {
            Throwable t = new CircuitBreakerOpenException(String.format("CircuitBreaker '%s' is open", circuitBreaker.getName()));
            if (recoverer != null) {
                try {
                    down.success(recoverer.apply(t));
                } catch (Throwable t2) {
                    down.error(t2);
                }
            } else {
                down.error(t);
            }
        }
    };
}
Also used : Downstream(ratpack.exec.Downstream) Function(ratpack.func.Function) CircuitBreaker(io.github.resilience4j.circuitbreaker.CircuitBreaker) Upstream(ratpack.exec.Upstream) CircuitBreakerOpenException(io.github.resilience4j.circuitbreaker.CircuitBreakerOpenException) Downstream(ratpack.exec.Downstream) CircuitBreakerOpenException(io.github.resilience4j.circuitbreaker.CircuitBreakerOpenException)

Example 2 with CircuitBreakerOpenException

use of io.github.resilience4j.circuitbreaker.CircuitBreakerOpenException in project resilience4j by resilience4j.

the class CircuitBreakerExportsTest method testExportsCircuitBreakerMetrics.

@Test
public void testExportsCircuitBreakerMetrics() {
    // Given
    final CollectorRegistry registry = new CollectorRegistry();
    final CircuitBreaker circuitBreaker = CircuitBreaker.ofDefaults("foo");
    CircuitBreakerExports.ofIterable("boo_circuit_breaker", singletonList(circuitBreaker)).register(registry);
    final Supplier<Map<String, Double>> values = () -> HashSet.of("successful", "failed", "not_permitted", "buffered", "buffered_max").map(callType -> Tuple.of(callType, registry.getSampleValue("boo_circuit_breaker_calls", new String[] { "name", "call_result" }, new String[] { "foo", callType }))).toMap(t -> t);
    // When
    final Map<String, Double> initialValues = values.get();
    circuitBreaker.executeRunnable(() -> {
    });
    final Map<String, Double> afterSuccessValues = values.get();
    try {
        circuitBreaker.executeRunnable(() -> {
            throw new SomeAppException("Some exception");
        });
    } catch (RuntimeException e) {
    // expected
    }
    final Map<String, Double> afterFailureValues = values.get();
    circuitBreaker.transitionToOpenState();
    try {
        circuitBreaker.executeRunnable(() -> {
        });
    } catch (CircuitBreakerOpenException e) {
    // expected
    }
    final Map<String, Double> afterDeclinedValues = values.get();
    // Then
    assertThat(initialValues).isEqualTo(HashMap.of("successful", 0.0, "failed", 0.0, "not_permitted", 0.0, "buffered", 0.0, "buffered_max", 100.0));
    assertThat(afterSuccessValues).isEqualTo(HashMap.of("successful", 1.0, "failed", 0.0, "not_permitted", 0.0, "buffered", 1.0, "buffered_max", 100.0));
    assertThat(afterFailureValues).isEqualTo(HashMap.of("successful", 1.0, "failed", 1.0, "not_permitted", 0.0, "buffered", 2.0, "buffered_max", 100.0));
    assertThat(afterDeclinedValues).isEqualTo(HashMap.of("successful", 1.0, "failed", 1.0, "not_permitted", 1.0, "buffered", 2.0, "buffered_max", 100.0));
}
Also used : Tuple(io.vavr.Tuple) CollectorRegistry(io.prometheus.client.CollectorRegistry) CircuitBreaker(io.github.resilience4j.circuitbreaker.CircuitBreaker) InMemoryCircuitBreakerRegistry(io.github.resilience4j.circuitbreaker.internal.InMemoryCircuitBreakerRegistry) HashMap(io.vavr.collection.HashMap) Assertions.assertThat(org.assertj.core.api.Assertions.assertThat) Test(org.junit.Test) Supplier(java.util.function.Supplier) CircuitBreakerOpenException(io.github.resilience4j.circuitbreaker.CircuitBreakerOpenException) CircuitBreakerRegistry(io.github.resilience4j.circuitbreaker.CircuitBreakerRegistry) Collections.singletonList(java.util.Collections.singletonList) Collections.singleton(java.util.Collections.singleton) HashSet(io.vavr.collection.HashSet) Map(io.vavr.collection.Map) CircuitBreaker(io.github.resilience4j.circuitbreaker.CircuitBreaker) CollectorRegistry(io.prometheus.client.CollectorRegistry) HashMap(io.vavr.collection.HashMap) Map(io.vavr.collection.Map) CircuitBreakerOpenException(io.github.resilience4j.circuitbreaker.CircuitBreakerOpenException) Test(org.junit.Test)

Example 3 with CircuitBreakerOpenException

use of io.github.resilience4j.circuitbreaker.CircuitBreakerOpenException in project resilience4j by resilience4j.

the class CircuitBreakerMethodInterceptor method invoke.

@SuppressWarnings("unchecked")
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
    CircuitBreaker annotation = invocation.getMethod().getAnnotation(CircuitBreaker.class);
    RecoveryFunction<?> recoveryFunction = annotation.recovery().newInstance();
    if (registry == null) {
        registry = CircuitBreakerRegistry.ofDefaults();
    }
    io.github.resilience4j.circuitbreaker.CircuitBreaker breaker = registry.circuitBreaker(annotation.name());
    if (breaker == null) {
        return invocation.proceed();
    }
    Class<?> returnType = invocation.getMethod().getReturnType();
    if (Promise.class.isAssignableFrom(returnType)) {
        Promise<?> result = (Promise<?>) proceed(invocation, breaker, recoveryFunction);
        if (result != null) {
            CircuitBreakerTransformer transformer = CircuitBreakerTransformer.of(breaker).recover(recoveryFunction);
            result = result.transform(transformer);
        }
        return result;
    } else if (Observable.class.isAssignableFrom(returnType)) {
        Observable<?> result = (Observable<?>) proceed(invocation, breaker, recoveryFunction);
        if (result != null) {
            CircuitBreakerOperator operator = CircuitBreakerOperator.of(breaker);
            result = result.lift(operator).onErrorReturn(t -> recoveryFunction.apply((Throwable) t));
        }
        return result;
    } else if (Flowable.class.isAssignableFrom(returnType)) {
        Flowable<?> result = (Flowable<?>) proceed(invocation, breaker, recoveryFunction);
        if (result != null) {
            CircuitBreakerOperator operator = CircuitBreakerOperator.of(breaker);
            result = result.lift(operator).onErrorReturn(t -> recoveryFunction.apply((Throwable) t));
        }
        return result;
    } else if (Single.class.isAssignableFrom(returnType)) {
        Single<?> result = (Single<?>) proceed(invocation, breaker, recoveryFunction);
        if (result != null) {
            CircuitBreakerOperator operator = CircuitBreakerOperator.of(breaker);
            result = result.lift(operator).onErrorReturn(t -> recoveryFunction.apply((Throwable) t));
        }
        return result;
    } else if (CompletionStage.class.isAssignableFrom(returnType)) {
        final CompletableFuture promise = new CompletableFuture<>();
        if (breaker.isCallPermitted()) {
            CompletionStage<?> result = (CompletionStage<?>) proceed(invocation, breaker, recoveryFunction);
            if (result != null) {
                long start = System.nanoTime();
                result.whenComplete((v, t) -> {
                    long durationInNanos = System.nanoTime() - start;
                    if (t != null) {
                        breaker.onError(durationInNanos, t);
                        try {
                            promise.complete(recoveryFunction.apply((Throwable) t));
                        } catch (Exception e) {
                            promise.completeExceptionally(e);
                        }
                    } else {
                        breaker.onSuccess(durationInNanos);
                        promise.complete(v);
                    }
                });
            }
        } else {
            Throwable t = new CircuitBreakerOpenException(String.format("CircuitBreaker '%s' is open", breaker.getName()));
            try {
                promise.complete(recoveryFunction.apply((Throwable) t));
            } catch (Throwable t2) {
                promise.completeExceptionally(t2);
            }
        }
        return promise;
    }
    return proceed(invocation, breaker, recoveryFunction);
}
Also used : CircuitBreakerOperator(io.github.resilience4j.circuitbreaker.operator.CircuitBreakerOperator) Inject(com.google.inject.Inject) Promise(ratpack.exec.Promise) CompletableFuture(java.util.concurrent.CompletableFuture) CircuitBreakerOperator(io.github.resilience4j.circuitbreaker.operator.CircuitBreakerOperator) CircuitBreakerOpenException(io.github.resilience4j.circuitbreaker.CircuitBreakerOpenException) CircuitBreakerRegistry(io.github.resilience4j.circuitbreaker.CircuitBreakerRegistry) Single(io.reactivex.Single) RecoveryFunction(io.github.resilience4j.ratpack.recovery.RecoveryFunction) MethodInterceptor(org.aopalliance.intercept.MethodInterceptor) MethodInvocation(org.aopalliance.intercept.MethodInvocation) CompletionStage(java.util.concurrent.CompletionStage) Flowable(io.reactivex.Flowable) Observable(io.reactivex.Observable) Observable(io.reactivex.Observable) CircuitBreakerOpenException(io.github.resilience4j.circuitbreaker.CircuitBreakerOpenException) CircuitBreakerOpenException(io.github.resilience4j.circuitbreaker.CircuitBreakerOpenException) Promise(ratpack.exec.Promise) CompletableFuture(java.util.concurrent.CompletableFuture) Single(io.reactivex.Single) CompletionStage(java.util.concurrent.CompletionStage) Flowable(io.reactivex.Flowable)

Example 4 with CircuitBreakerOpenException

use of io.github.resilience4j.circuitbreaker.CircuitBreakerOpenException in project resilience4j by resilience4j.

the class RetrofitCircuitBreaker method decorateCall.

/**
 * Decorate {@link Call}s allow {@link CircuitBreaker} functionality.
 *
 * @param circuitBreaker  {@link CircuitBreaker} to apply
 * @param call            Call to decorate
 * @param responseSuccess determines whether the response should be considered an expected response
 * @param <T> Response type of call
 * @return Original Call decorated with CircuitBreaker
 */
static <T> Call<T> decorateCall(final CircuitBreaker circuitBreaker, final Call<T> call, final Predicate<Response> responseSuccess) {
    return new DecoratedCall<T>(call) {

        @Override
        public void enqueue(final Callback<T> callback) {
            try {
                CircuitBreakerUtils.isCallPermitted(circuitBreaker);
            } catch (CircuitBreakerOpenException cb) {
                callback.onFailure(call, cb);
            }
            final StopWatch stopWatch = StopWatch.start(circuitBreaker.getName());
            call.enqueue(new Callback<T>() {

                @Override
                public void onResponse(final Call<T> call, final Response<T> response) {
                    if (responseSuccess.test(response)) {
                        circuitBreaker.onSuccess(stopWatch.stop().getProcessingDuration().toNanos());
                    } else {
                        final Throwable throwable = new Throwable("Response error: HTTP " + response.code() + " - " + response.message());
                        circuitBreaker.onError(stopWatch.stop().getProcessingDuration().toNanos(), throwable);
                    }
                    callback.onResponse(call, response);
                }

                @Override
                public void onFailure(final Call<T> call, final Throwable t) {
                    circuitBreaker.onError(stopWatch.stop().getProcessingDuration().toNanos(), t);
                    callback.onFailure(call, t);
                }
            });
        }

        @Override
        public Response<T> execute() throws IOException {
            CircuitBreakerUtils.isCallPermitted(circuitBreaker);
            final StopWatch stopWatch = StopWatch.start(circuitBreaker.getName());
            try {
                final Response<T> response = call.execute();
                if (responseSuccess.test(response)) {
                    circuitBreaker.onSuccess(stopWatch.stop().getProcessingDuration().toNanos());
                } else {
                    final Throwable throwable = new Throwable("Response error: HTTP " + response.code() + " - " + response.message());
                    circuitBreaker.onError(stopWatch.stop().getProcessingDuration().toNanos(), throwable);
                }
                return response;
            } catch (Throwable throwable) {
                circuitBreaker.onError(stopWatch.stop().getProcessingDuration().toNanos(), throwable);
                throw throwable;
            }
        }
    };
}
Also used : DecoratedCall(io.github.resilience4j.retrofit.internal.DecoratedCall) Callback(retrofit2.Callback) CircuitBreakerOpenException(io.github.resilience4j.circuitbreaker.CircuitBreakerOpenException) StopWatch(io.github.resilience4j.core.StopWatch)

Example 5 with CircuitBreakerOpenException

use of io.github.resilience4j.circuitbreaker.CircuitBreakerOpenException in project resilience4j by resilience4j.

the class CircuitBreakerSubscriber method onSubscribe.

@Override
public void onSubscribe(Subscription subscription) {
    if (SubscriptionHelper.setOnce(this, subscription)) {
        if (acquireCallPermit()) {
            childSubscriber.onSubscribe(this);
        } else {
            cancel();
            childSubscriber.onSubscribe(this);
            childSubscriber.onError(new CircuitBreakerOpenException(String.format("CircuitBreaker '%s' is open", circuitBreaker.getName())));
        }
    }
}
Also used : CircuitBreakerOpenException(io.github.resilience4j.circuitbreaker.CircuitBreakerOpenException)

Aggregations

CircuitBreakerOpenException (io.github.resilience4j.circuitbreaker.CircuitBreakerOpenException)5 CircuitBreaker (io.github.resilience4j.circuitbreaker.CircuitBreaker)2 CircuitBreakerRegistry (io.github.resilience4j.circuitbreaker.CircuitBreakerRegistry)2 Inject (com.google.inject.Inject)1 InMemoryCircuitBreakerRegistry (io.github.resilience4j.circuitbreaker.internal.InMemoryCircuitBreakerRegistry)1 CircuitBreakerOperator (io.github.resilience4j.circuitbreaker.operator.CircuitBreakerOperator)1 StopWatch (io.github.resilience4j.core.StopWatch)1 RecoveryFunction (io.github.resilience4j.ratpack.recovery.RecoveryFunction)1 DecoratedCall (io.github.resilience4j.retrofit.internal.DecoratedCall)1 CollectorRegistry (io.prometheus.client.CollectorRegistry)1 Flowable (io.reactivex.Flowable)1 Observable (io.reactivex.Observable)1 Single (io.reactivex.Single)1 Tuple (io.vavr.Tuple)1 HashMap (io.vavr.collection.HashMap)1 HashSet (io.vavr.collection.HashSet)1 Map (io.vavr.collection.Map)1 Collections.singleton (java.util.Collections.singleton)1 Collections.singletonList (java.util.Collections.singletonList)1 CompletableFuture (java.util.concurrent.CompletableFuture)1