Search in sources :

Example 1 with HelloWorldException

use of io.github.resilience4j.test.HelloWorldException in project resilience4j by resilience4j.

the class DecoratorsTest method testDecorateCompletionStagePropagatesContextWithRetryAsync.

@Test
public void testDecorateCompletionStagePropagatesContextWithRetryAsync() {
    given(helloWorldService.returnHelloWorld()).willReturn("Hello world");
    CircuitBreaker circuitBreaker = CircuitBreaker.ofDefaults("helloBackend");
    TestThreadLocalContextPropagatorWithHolder propagator = new TestThreadLocalContextPropagatorWithHolder();
    TestThreadLocalContextHolder.put("ValueShouldCrossThreadBoundary");
    ContextAwareScheduledThreadPoolExecutor scheduledThreadPool = ContextAwareScheduledThreadPoolExecutor.newScheduledThreadPool().corePoolSize(1).contextPropagators(propagator).build();
    CompletableFuture<String> failedFuture = new CompletableFuture<>();
    failedFuture.completeExceptionally(new HelloWorldException());
    given(asyncHelloWorldService.returnHelloWorld()).willReturn(failedFuture);
    CompletionStage<String> completionStage = Decorators.ofCompletionStage(() -> asyncHelloWorldService.returnHelloWorld()).withCircuitBreaker(circuitBreaker).withRetry(Retry.ofDefaults("id"), scheduledThreadPool).withBulkhead(Bulkhead.ofDefaults("testName")).get();
    final CompletableFuture<String> completableFuture = completionStage.toCompletableFuture().exceptionally(throwable -> {
        if (throwable != null) {
            assertThat(Thread.currentThread().getName()).contains("ContextAwareScheduledThreadPool");
            assertThat(TestThreadLocalContextHolder.get().get()).isEqualTo("ValueShouldCrossThreadBoundary");
            return (String) TestThreadLocalContextHolder.get().orElse(null);
        }
        return null;
    });
    waitAtMost(2, TimeUnit.SECONDS).until(matches(() -> assertThat(completableFuture).isCompletedWithValue("ValueShouldCrossThreadBoundary")));
    CircuitBreaker.Metrics metrics = circuitBreaker.getMetrics();
    assertThat(metrics.getNumberOfBufferedCalls()).isEqualTo(3);
    assertThat(metrics.getNumberOfFailedCalls()).isEqualTo(3);
    then(asyncHelloWorldService).should(times(3)).returnHelloWorld();
}
Also used : CircuitBreaker(io.github.resilience4j.circuitbreaker.CircuitBreaker) HelloWorldException(io.github.resilience4j.test.HelloWorldException) ContextAwareScheduledThreadPoolExecutor(io.github.resilience4j.core.ContextAwareScheduledThreadPoolExecutor) TestThreadLocalContextPropagatorWithHolder(io.github.resilience4j.test.TestContextPropagators.TestThreadLocalContextPropagatorWithHolder) Test(org.junit.Test)

Example 2 with HelloWorldException

use of io.github.resilience4j.test.HelloWorldException in project resilience4j by resilience4j.

the class DecoratorsTest method testDecorateCompletionStagePropagatesMDCContextWithRetryAsync.

@Test
public void testDecorateCompletionStagePropagatesMDCContextWithRetryAsync() {
    given(helloWorldService.returnHelloWorld()).willReturn("Hello world");
    CircuitBreaker circuitBreaker = CircuitBreaker.ofDefaults("helloBackend");
    MDC.put("key", "ValueShouldCrossThreadBoundary");
    MDC.put("key2", "value2");
    final Map<String, String> contextMap = MDC.getCopyOfContextMap();
    ContextAwareScheduledThreadPoolExecutor scheduledThreadPool = ContextAwareScheduledThreadPoolExecutor.newScheduledThreadPool().corePoolSize(1).build();
    CompletableFuture<String> failedFuture = new CompletableFuture<>();
    failedFuture.completeExceptionally(new HelloWorldException());
    given(asyncHelloWorldService.returnHelloWorld()).willReturn(failedFuture);
    CompletionStage<String> completionStage = Decorators.ofCompletionStage(() -> asyncHelloWorldService.returnHelloWorld()).withCircuitBreaker(circuitBreaker).withRetry(Retry.ofDefaults("id"), scheduledThreadPool).withBulkhead(Bulkhead.ofDefaults("testName")).get();
    final CompletableFuture<String> completableFuture = completionStage.toCompletableFuture().exceptionally(throwable -> {
        if (throwable != null) {
            assertThat(Thread.currentThread().getName()).contains("ContextAwareScheduledThreadPool");
            assertThat(MDC.getCopyOfContextMap()).hasSize(2).containsExactlyEntriesOf(contextMap);
            return MDC.getCopyOfContextMap().get("key");
        }
        return null;
    });
    waitAtMost(2, TimeUnit.SECONDS).until(matches(() -> assertThat(completableFuture).isCompletedWithValue("ValueShouldCrossThreadBoundary")));
    CircuitBreaker.Metrics metrics = circuitBreaker.getMetrics();
    assertThat(metrics.getNumberOfBufferedCalls()).isEqualTo(3);
    assertThat(metrics.getNumberOfFailedCalls()).isEqualTo(3);
    then(asyncHelloWorldService).should(times(3)).returnHelloWorld();
}
Also used : CircuitBreaker(io.github.resilience4j.circuitbreaker.CircuitBreaker) HelloWorldException(io.github.resilience4j.test.HelloWorldException) ContextAwareScheduledThreadPoolExecutor(io.github.resilience4j.core.ContextAwareScheduledThreadPoolExecutor) Test(org.junit.Test)

Example 3 with HelloWorldException

use of io.github.resilience4j.test.HelloWorldException in project resilience4j by resilience4j.

the class BulkheadTest method shouldDecorateCompletionStageAndReturnWithExceptionAtSyncStage.

@Test
public void shouldDecorateCompletionStageAndReturnWithExceptionAtSyncStage() {
    Bulkhead bulkhead = Bulkhead.of("test", config);
    Supplier<CompletionStage<String>> completionStageSupplier = () -> {
        throw new HelloWorldException();
    };
    Supplier<CompletionStage<String>> decoratedCompletionStageSupplier = Bulkhead.decorateCompletionStage(bulkhead, completionStageSupplier);
    // NOTE: Try.of does not detect a completion stage that has been completed with failure!
    Try<CompletionStage<String>> result = Try.of(decoratedCompletionStageSupplier::get);
    then(helloWorldService).should(times(0)).returnHelloWorld();
    assertThat(result.isSuccess()).isTrue();
    result.get().exceptionally(error -> {
        // NOTE: Try.of does not detect a completion stage that has been completed with failure!
        assertThat(error).isInstanceOf(HelloWorldException.class);
        return null;
    });
    assertThat(bulkhead.getMetrics().getAvailableConcurrentCalls()).isEqualTo(1);
}
Also used : HelloWorldException(io.github.resilience4j.test.HelloWorldException) CompletionStage(java.util.concurrent.CompletionStage) Test(org.junit.Test)

Example 4 with HelloWorldException

use of io.github.resilience4j.test.HelloWorldException in project resilience4j by resilience4j.

the class CircuitBreakerTest method shouldNotRecordIOExceptionAsAFailure.

@Test
public void shouldNotRecordIOExceptionAsAFailure() {
    // tag::shouldNotRecordIOExceptionAsAFailure[]
    CircuitBreakerConfig circuitBreakerConfig = CircuitBreakerConfig.custom().slidingWindowSize(2).permittedNumberOfCallsInHalfOpenState(2).waitDurationInOpenState(Duration.ofMillis(1000)).ignoreExceptions(IOException.class).build();
    CircuitBreaker circuitBreaker = CircuitBreaker.of("testName", circuitBreakerConfig);
    // Simulate a failure attempt
    circuitBreaker.onError(0, TimeUnit.NANOSECONDS, new HelloWorldException());
    // CircuitBreaker is still CLOSED, because 1 failure is allowed
    assertThat(circuitBreaker.getState()).isEqualTo(CircuitBreaker.State.CLOSED);
    CheckedRunnable checkedRunnable = circuitBreaker.decorateCheckedRunnable(() -> {
        throw new SocketTimeoutException("BAM!");
    });
    Try result = Try.run(() -> checkedRunnable.run());
    assertThat(result.isFailure()).isTrue();
    // CircuitBreaker is still CLOSED, because SocketTimeoutException has not been recorded as a failure
    assertThat(circuitBreaker.getState()).isEqualTo(CircuitBreaker.State.CLOSED);
    assertThat(result.failed().get()).isInstanceOf(IOException.class);
    // end::shouldNotRecordIOExceptionAsAFailure[]
    CircuitBreaker.Metrics metrics = circuitBreaker.getMetrics();
    assertThat(metrics.getNumberOfBufferedCalls()).isEqualTo(1);
    assertThat(metrics.getNumberOfFailedCalls()).isEqualTo(1);
}
Also used : SocketTimeoutException(java.net.SocketTimeoutException) CheckedRunnable(io.github.resilience4j.core.functions.CheckedRunnable) HelloWorldException(io.github.resilience4j.test.HelloWorldException) Try(io.vavr.control.Try) IOException(java.io.IOException) Test(org.junit.Test)

Example 5 with HelloWorldException

use of io.github.resilience4j.test.HelloWorldException in project resilience4j by resilience4j.

the class CircuitBreakerTest method shouldNotRecordIOExceptionAsAFailureWithFuture.

@Test
public void shouldNotRecordIOExceptionAsAFailureWithFuture() throws Exception {
    // tag::shouldNotRecordIOExceptionAsAFailure[]
    CircuitBreakerConfig circuitBreakerConfig = CircuitBreakerConfig.custom().slidingWindowSize(2).permittedNumberOfCallsInHalfOpenState(2).waitDurationInOpenState(Duration.ofMillis(1000)).ignoreExceptions(IOException.class).build();
    CircuitBreaker circuitBreaker = CircuitBreaker.of("testName", circuitBreakerConfig);
    // Simulate a failure attempt
    circuitBreaker.onError(0, TimeUnit.NANOSECONDS, new HelloWorldException());
    // CircuitBreaker is still CLOSED, because 1 failure is allowed
    assertThat(circuitBreaker.getState()).isEqualTo(CircuitBreaker.State.CLOSED);
    Future<String> future = mock(Future.class);
    given(future.get()).willThrow(new ExecutionException(new SocketTimeoutException("BAM!")));
    given(helloWorldService.returnHelloWorldFuture()).willReturn(future);
    Supplier<Future<String>> futureSupplier = circuitBreaker.decorateFuture(helloWorldService::returnHelloWorldFuture);
    // When
    Throwable thrown = catchThrowable(() -> futureSupplier.get().get());
    // Then
    // CircuitBreaker is still CLOSED, because SocketTimeoutException has not been recorded as a failure
    assertThat(circuitBreaker.getState()).isEqualTo(CircuitBreaker.State.CLOSED);
    // end::shouldNotRecordIOExceptionAsAFailure[]
    assertThat(thrown).isInstanceOf(ExecutionException.class);
    assertThat(thrown).hasCauseInstanceOf(IOException.class);
    CircuitBreaker.Metrics metrics = circuitBreaker.getMetrics();
    assertThat(metrics.getNumberOfBufferedCalls()).isEqualTo(1);
    // this failure is because of HelloWorldException thrown earlier
    assertThat(metrics.getNumberOfFailedCalls()).isEqualTo(1);
    then(helloWorldService).should().returnHelloWorldFuture();
    then(future).should().get();
}
Also used : HelloWorldException(io.github.resilience4j.test.HelloWorldException) IOException(java.io.IOException) SocketTimeoutException(java.net.SocketTimeoutException) Test(org.junit.Test)

Aggregations

HelloWorldException (io.github.resilience4j.test.HelloWorldException)85 Test (org.junit.Test)84 Retry (io.github.resilience4j.retry.Retry)60 RetryConfig (io.github.resilience4j.retry.RetryConfig)45 HelloWorldService (io.github.resilience4j.test.HelloWorldService)16 IOException (java.io.IOException)16 Assertions.assertThat (org.assertj.core.api.Assertions.assertThat)16 Before (org.junit.Before)16 BDDMockito.then (org.mockito.BDDMockito.then)15 BDDMockito.given (org.mockito.BDDMockito.given)14 Duration (java.time.Duration)13 MaxRetriesExceededException (io.github.resilience4j.retry.MaxRetriesExceededException)12 Mockito (org.mockito.Mockito)10 CheckedRunnable (io.github.resilience4j.core.functions.CheckedRunnable)9 CheckedRunnable (io.vavr.CheckedRunnable)8 Try (io.vavr.control.Try)7 Mockito.mock (org.mockito.Mockito.mock)6 Mockito.times (org.mockito.Mockito.times)6 io.reactivex (io.reactivex)5 io.reactivex.rxjava3.core (io.reactivex.rxjava3.core)5