public DecorateCompletionStage<T> withCircuitBreaker(CircuitBreaker circuitBreaker) { stageSupplier = CircuitBreaker.decorateCompletionStage(circuitBreaker, stageSupplier); return this; }
/** * Decorates and executes the decorated CompletionStage. * * @param supplier the original CompletionStage * @param <T> the type of results supplied by this supplier * @return the decorated CompletionStage. */ default <T> CompletionStage<T> executeCompletionStage(Supplier<CompletionStage<T>> supplier){ return decorateCompletionStage(this, supplier).get(); }
@Test public void shouldDecorateCompletionStageAndReturnWithExceptionAtSyncStage() throws ExecutionException, InterruptedException { // Given CircuitBreaker circuitBreaker = CircuitBreaker.ofDefaults("backendName"); assertThat(circuitBreaker.getState()).isEqualTo(CircuitBreaker.State.CLOSED); // Given the HelloWorldService throws an exception // When Supplier<CompletionStage<String>> completionStageSupplier = () -> { throw new WebServiceException("BAM! At sync stage"); }; Supplier<CompletionStage<String>> decoratedCompletionStageSupplier = CircuitBreaker.decorateCompletionStage(circuitBreaker, completionStageSupplier); Try<CompletionStage<String>> result = Try.of(decoratedCompletionStageSupplier::get); assertThat(result.isFailure()).isEqualTo(true); assertThat(result.failed().get()).isInstanceOf(WebServiceException.class); CircuitBreaker.Metrics metrics = circuitBreaker.getMetrics(); assertThat(metrics.getNumberOfBufferedCalls()).isEqualTo(1); assertThat(metrics.getNumberOfFailedCalls()).isEqualTo(1); }
@Test public void shouldDecorateCompletionStageAndReturnWithExceptionAtAsyncStage() throws ExecutionException, InterruptedException { // Given CircuitBreaker circuitBreaker = CircuitBreaker.ofDefaults("backendName"); assertThat(circuitBreaker.getState()).isEqualTo(CircuitBreaker.State.CLOSED); // Given the HelloWorldService throws an exception BDDMockito.given(helloWorldService.returnHelloWorld()).willThrow(new RuntimeException("BAM! At async stage")); // When Supplier<CompletionStage<String>> completionStageSupplier = () -> CompletableFuture.supplyAsync(helloWorldService::returnHelloWorld); Supplier<CompletionStage<String>> decoratedCompletionStageSupplier = CircuitBreaker.decorateCompletionStage(circuitBreaker, completionStageSupplier); CompletionStage<String> decoratedCompletionStage = decoratedCompletionStageSupplier.get(); // Then the helloWorldService should be invoked 1 time assertThatThrownBy(decoratedCompletionStage.toCompletableFuture()::get) .isInstanceOf(ExecutionException.class).hasCause(new RuntimeException("BAM! At async stage")); BDDMockito.then(helloWorldService).should(Mockito.times(1)).returnHelloWorld(); CircuitBreaker.Metrics metrics = circuitBreaker.getMetrics(); assertThat(metrics.getNumberOfBufferedCalls()).isEqualTo(1); assertThat(metrics.getNumberOfFailedCalls()).isEqualTo(1); }
@Test public void shouldDecorateCompletionStageAndReturnWithSuccess() throws ExecutionException, InterruptedException { // Given CircuitBreaker circuitBreaker = CircuitBreaker.ofDefaults("backendName"); assertThat(circuitBreaker.getState()).isEqualTo(CircuitBreaker.State.CLOSED); // Given the HelloWorldService returns Hello world BDDMockito.given(helloWorldService.returnHelloWorld()).willReturn("Hello"); // When Supplier<CompletionStage<String>> completionStageSupplier = () -> CompletableFuture.supplyAsync(helloWorldService::returnHelloWorld); Supplier<CompletionStage<String>> decoratedCompletionStageSupplier = CircuitBreaker.decorateCompletionStage(circuitBreaker, completionStageSupplier); CompletionStage<String> decoratedCompletionStage = decoratedCompletionStageSupplier .get() .thenApply(value -> value + " world"); // Then the helloWorldService should be invoked 1 time assertThat(decoratedCompletionStage.toCompletableFuture().get()).isEqualTo("Hello world"); BDDMockito.then(helloWorldService).should(Mockito.times(1)).returnHelloWorld(); CircuitBreaker.Metrics metrics = circuitBreaker.getMetrics(); assertThat(metrics.getNumberOfBufferedCalls()).isEqualTo(1); assertThat(metrics.getNumberOfFailedCalls()).isEqualTo(0); }