Search in sources :

Example 1 with CircuitBreakerOpenException

use of com.nike.fastbreak.exception.CircuitBreakerOpenException in project riposte by Nike-Inc.

the class AsyncHttpClientHelperTest method executeAsyncHttpRequest_completes_future_if_exception_happens_during_setup.

@DataProvider(value = { "true", "false" }, splitBy = "\\|")
@Test
public void executeAsyncHttpRequest_completes_future_if_exception_happens_during_setup(boolean throwCircuitBreakerOpenException) {
    // given
    RuntimeException exToThrow = (throwCircuitBreakerOpenException) ? new CircuitBreakerOpenException("foo", "kaboom") : new RuntimeException("kaboom");
    doThrow(exToThrow).when(helperSpy).getCircuitBreaker(any(RequestBuilderWrapper.class));
    Logger loggerMock = mock(Logger.class);
    Whitebox.setInternalState(helperSpy, "logger", loggerMock);
    // when
    CompletableFuture result = helperSpy.executeAsyncHttpRequest(mock(RequestBuilderWrapper.class), mock(AsyncResponseHandler.class), null, null);
    // then
    assertThat(result).isCompletedExceptionally();
    Throwable ex = catchThrowable(result::get);
    assertThat(ex).isInstanceOf(ExecutionException.class).hasCause(exToThrow);
    if (throwCircuitBreakerOpenException)
        verifyNoInteractions(loggerMock);
    else
        verify(loggerMock).error(anyString(), any(), any(), eq(exToThrow));
}
Also used : CompletableFuture(java.util.concurrent.CompletableFuture) Assertions.catchThrowable(org.assertj.core.api.Assertions.catchThrowable) Logger(org.slf4j.Logger) ExecutionException(java.util.concurrent.ExecutionException) CircuitBreakerOpenException(com.nike.fastbreak.exception.CircuitBreakerOpenException) DataProvider(com.tngtech.java.junit.dataprovider.DataProvider) Test(org.junit.Test)

Example 2 with CircuitBreakerOpenException

use of com.nike.fastbreak.exception.CircuitBreakerOpenException in project riposte by Nike-Inc.

the class AsyncHttpClientHelperTest method executeAsyncHttpRequest_completes_future_if_exception_happens_during_setup.

@DataProvider(value = { "true", "false" }, splitBy = "\\|")
@Test
public void executeAsyncHttpRequest_completes_future_if_exception_happens_during_setup(boolean throwCircuitBreakerOpenException) {
    // given
    RuntimeException exToThrow = (throwCircuitBreakerOpenException) ? new CircuitBreakerOpenException("foo", "kaboom") : new RuntimeException("kaboom");
    doThrow(exToThrow).when(helperSpy).getCircuitBreaker(any(RequestBuilderWrapper.class));
    Logger loggerMock = mock(Logger.class);
    Whitebox.setInternalState(helperSpy, "logger", loggerMock);
    // when
    CompletableFuture result = helperSpy.executeAsyncHttpRequest(mock(RequestBuilderWrapper.class), mock(AsyncResponseHandler.class), null, null);
    // then
    assertThat(result).isCompletedExceptionally();
    Throwable ex = catchThrowable(result::get);
    assertThat(ex).isInstanceOf(ExecutionException.class).hasCause(exToThrow);
    if (throwCircuitBreakerOpenException)
        verifyNoInteractions(loggerMock);
    else
        verify(loggerMock).error(anyString(), any(), any(), eq(exToThrow));
}
Also used : CompletableFuture(java.util.concurrent.CompletableFuture) Assertions.catchThrowable(org.assertj.core.api.Assertions.catchThrowable) Logger(org.slf4j.Logger) ExecutionException(java.util.concurrent.ExecutionException) CircuitBreakerOpenException(com.nike.fastbreak.exception.CircuitBreakerOpenException) DataProvider(com.tngtech.java.junit.dataprovider.DataProvider) Test(org.junit.Test)

Example 3 with CircuitBreakerOpenException

use of com.nike.fastbreak.exception.CircuitBreakerOpenException in project riposte by Nike-Inc.

the class AsyncHttpClientHelper method executeAsyncHttpRequest.

/**
 * Executes the given request asynchronously, handling the response with the given responseHandlerFunction, and
 * returns a {@link CompletableFuture} that represents the result of executing the
 * responseHandlerFunction on the downstream response. Any error anywhere along the way will cause the returned
 * future to be completed with {@link CompletableFuture#completeExceptionally(Throwable)}.
 * <p/>
 * <b>Distributed Tracing and MDC for the downstream call:</b> The given {@code distributedTraceStackForCall} and
 * {@code mdcContextForCall} arguments are used to setup distributed trace and MDC info for the downstream call so
 * that the callback will be performed with that data attached to whatever thread the callback is done on.
 */
public <O> CompletableFuture<O> executeAsyncHttpRequest(RequestBuilderWrapper requestBuilderWrapper, AsyncResponseHandler<O> responseHandlerFunction, Deque<Span> distributedTraceStackForCall, Map<String, String> mdcContextForCall) {
    CompletableFuture<O> completableFutureResponse = new CompletableFuture<>();
    try {
        Optional<ManualModeTask<Response>> circuitBreakerManualTask = getCircuitBreaker(requestBuilderWrapper).map(CircuitBreaker::newManualModeTask);
        // If we have a circuit breaker, give it a chance to throw an exception if the circuit is open/tripped
        circuitBreakerManualTask.ifPresent(ManualModeTask::throwExceptionIfCircuitBreakerIsOpen);
        // Setup the async completion handler for the call.
        AsyncCompletionHandlerWithTracingAndMdcSupport<O> asyncCompletionHandler = new AsyncCompletionHandlerWithTracingAndMdcSupport<>(completableFutureResponse, responseHandlerFunction, performSubSpanAroundDownstreamCalls, requestBuilderWrapper, circuitBreakerManualTask, distributedTraceStackForCall, mdcContextForCall, spanNamingAndTaggingStrategy);
        // Add distributed trace headers to the downstream call if we have a span.
        Span spanForCall = asyncCompletionHandler.getSpanForCall();
        if (spanForCall != null) {
            HttpRequestTracingUtils.propagateTracingHeaders((headerKey, headerValue) -> {
                if (headerValue != null) {
                    requestBuilderWrapper.requestBuilder.setHeader(headerKey, headerValue);
                }
            }, spanForCall);
        }
        // Add span tags if we're doing a subspan around the call.
        if (performSubSpanAroundDownstreamCalls && spanForCall != null) {
            spanNamingAndTaggingStrategy.handleRequestTagging(spanForCall, requestBuilderWrapper);
        }
        // Execute the downstream call. The completableFutureResponse will be completed or completed exceptionally
        // depending on the result of the call.
        requestBuilderWrapper.requestBuilder.execute(asyncCompletionHandler);
    } catch (Throwable t) {
        // normal when the circuit breaker associated with this request has been tripped.
        if (!(t instanceof CircuitBreakerOpenException)) {
            logger.error("An error occurred while trying to set up an async HTTP call for method {} and URL {}. " + "The CompletableFuture will be instantly failed with this error", requestBuilderWrapper.httpMethod, requestBuilderWrapper.url, t);
        }
        completableFutureResponse.completeExceptionally(t);
    }
    return completableFutureResponse;
}
Also used : CompletableFuture(java.util.concurrent.CompletableFuture) CircuitBreaker(com.nike.fastbreak.CircuitBreaker) ManualModeTask(com.nike.fastbreak.CircuitBreaker.ManualModeTask) Span(com.nike.wingtips.Span) CircuitBreakerOpenException(com.nike.fastbreak.exception.CircuitBreakerOpenException)

Example 4 with CircuitBreakerOpenException

use of com.nike.fastbreak.exception.CircuitBreakerOpenException in project riposte by Nike-Inc.

the class AsyncHttpClientHelper method executeAsyncHttpRequest.

/**
 * Executes the given request asynchronously, handling the response with the given responseHandlerFunction, and
 * returns a {@link CompletableFuture} that represents the result of executing the
 * responseHandlerFunction on the downstream response. Any error anywhere along the way will cause the returned
 * future to be completed with {@link CompletableFuture#completeExceptionally(Throwable)}.
 * <p/>
 * <b>Distributed Tracing and MDC for the downstream call:</b> The given {@code distributedTraceStackForCall} and
 * {@code mdcContextForCall} arguments are used to setup distributed trace and MDC info for the downstream call so
 * that the callback will be performed with that data attached to whatever thread the callback is done on.
 */
public <O> CompletableFuture<O> executeAsyncHttpRequest(RequestBuilderWrapper requestBuilderWrapper, AsyncResponseHandler<O> responseHandlerFunction, Deque<Span> distributedTraceStackForCall, Map<String, String> mdcContextForCall) {
    CompletableFuture<O> completableFutureResponse = new CompletableFuture<>();
    try {
        Optional<ManualModeTask<Response>> circuitBreakerManualTask = getCircuitBreaker(requestBuilderWrapper).map(CircuitBreaker::newManualModeTask);
        // If we have a circuit breaker, give it a chance to throw an exception if the circuit is open/tripped
        circuitBreakerManualTask.ifPresent(ManualModeTask::throwExceptionIfCircuitBreakerIsOpen);
        // Setup the async completion handler for the call.
        AsyncCompletionHandlerWithTracingAndMdcSupport<O> asyncCompletionHandler = new AsyncCompletionHandlerWithTracingAndMdcSupport<>(completableFutureResponse, responseHandlerFunction, performSubSpanAroundDownstreamCalls, requestBuilderWrapper, circuitBreakerManualTask, distributedTraceStackForCall, mdcContextForCall, spanNamingAndTaggingStrategy);
        // Add distributed trace headers to the downstream call if we have a span.
        Span spanForCall = asyncCompletionHandler.getSpanForCall();
        if (spanForCall != null) {
            HttpRequestTracingUtils.propagateTracingHeaders((headerKey, headerValue) -> {
                if (headerValue != null) {
                    requestBuilderWrapper.requestBuilder.setHeader(headerKey, headerValue);
                }
            }, spanForCall);
        }
        // Add span tags if we're doing a subspan around the call.
        if (performSubSpanAroundDownstreamCalls && spanForCall != null) {
            spanNamingAndTaggingStrategy.handleRequestTagging(spanForCall, requestBuilderWrapper);
        }
        // Execute the downstream call. The completableFutureResponse will be completed or completed exceptionally
        // depending on the result of the call.
        requestBuilderWrapper.requestBuilder.execute(asyncCompletionHandler);
    } catch (Throwable t) {
        // normal when the circuit breaker associated with this request has been tripped.
        if (!(t instanceof CircuitBreakerOpenException)) {
            logger.error("An error occurred while trying to set up an async HTTP call for method {} and URL {}. " + "The CompletableFuture will be instantly failed with this error", requestBuilderWrapper.httpMethod, requestBuilderWrapper.url, t);
        }
        completableFutureResponse.completeExceptionally(t);
    }
    return completableFutureResponse;
}
Also used : CompletableFuture(java.util.concurrent.CompletableFuture) CircuitBreaker(com.nike.fastbreak.CircuitBreaker) ManualModeTask(com.nike.fastbreak.CircuitBreaker.ManualModeTask) Span(com.nike.wingtips.Span) CircuitBreakerOpenException(com.nike.fastbreak.exception.CircuitBreakerOpenException)

Example 5 with CircuitBreakerOpenException

use of com.nike.fastbreak.exception.CircuitBreakerOpenException in project riposte by Nike-Inc.

the class BackstopperRiposteFrameworkErrorHandlerListenerTest method should_handle_CircuitBreakerException.

@Test
public void should_handle_CircuitBreakerException() {
    verifyExceptionHandled(new CircuitBreakerOpenException("foo", "bar"), singletonError(listener.CIRCUIT_BREAKER_OPEN_API_ERROR));
    verifyExceptionHandled(new CircuitBreakerTimeoutException("foo", "bar"), singletonError(listener.CIRCUIT_BREAKER_TIMEOUT_API_ERROR));
    verifyExceptionHandled(new CircuitBreakerException("foo", "bar") {
    }, singletonError(listener.CIRCUIT_BREAKER_GENERIC_API_ERROR));
}
Also used : CircuitBreakerException(com.nike.fastbreak.exception.CircuitBreakerException) CircuitBreakerTimeoutException(com.nike.fastbreak.exception.CircuitBreakerTimeoutException) CircuitBreakerOpenException(com.nike.fastbreak.exception.CircuitBreakerOpenException) Test(org.junit.Test)

Aggregations

CircuitBreakerOpenException (com.nike.fastbreak.exception.CircuitBreakerOpenException)5 CompletableFuture (java.util.concurrent.CompletableFuture)4 Test (org.junit.Test)3 CircuitBreaker (com.nike.fastbreak.CircuitBreaker)2 ManualModeTask (com.nike.fastbreak.CircuitBreaker.ManualModeTask)2 Span (com.nike.wingtips.Span)2 DataProvider (com.tngtech.java.junit.dataprovider.DataProvider)2 ExecutionException (java.util.concurrent.ExecutionException)2 Assertions.catchThrowable (org.assertj.core.api.Assertions.catchThrowable)2 Logger (org.slf4j.Logger)2 CircuitBreakerException (com.nike.fastbreak.exception.CircuitBreakerException)1 CircuitBreakerTimeoutException (com.nike.fastbreak.exception.CircuitBreakerTimeoutException)1