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();
}
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();
}
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);
}
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);
}
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();
}
Aggregations