@Test public void testChainOfTwo() throws Exception { HttpUnsuccessfulResponseHandler handler1 = mock(HttpUnsuccessfulResponseHandler.class); HttpUnsuccessfulResponseHandler handler2 = mock(HttpUnsuccessfulResponseHandler.class); chainer.chain(handler1, handler2) .handleResponse(httpRequest, httpResponse, SUPPORTS_RETRY); verify(handler1) .handleResponse( any(HttpRequest.class), any(HttpResponse.class), any(Boolean.TYPE)); verify(handler2) .handleResponse( any(HttpRequest.class), any(HttpResponse.class), any(Boolean.TYPE)); }
@Test public void testChainOnlyCallsUntilTrue() throws Exception { HttpUnsuccessfulResponseHandler handler1 = mock(HttpUnsuccessfulResponseHandler.class); HttpUnsuccessfulResponseHandler handler2 = mock(HttpUnsuccessfulResponseHandler.class); when(handler1.handleResponse( any(HttpRequest.class), any(HttpResponse.class), anyBoolean())) .thenReturn(true); chainer.chain(handler1, handler2) .handleResponse(httpRequest, httpResponse, SUPPORTS_RETRY); verify(handler1) .handleResponse( any(HttpRequest.class), any(HttpResponse.class), any(Boolean.TYPE)); verify(handler2, never()) .handleResponse( any(HttpRequest.class), any(HttpResponse.class), any(Boolean.TYPE)); }
private static HttpRequestInitializer setHttpBackoffTimeout(final HttpRequestInitializer requestInitializer, final int connectTimeoutMs, final int readTimeoutMs) { return new HttpRequestInitializer() { @Override public void initialize(HttpRequest httpRequest) throws IOException { requestInitializer.initialize(httpRequest); // Configure exponential backoff on error // https://developers.google.com/api-client-library/java/google-http-java-client/backoff ExponentialBackOff backoff = new ExponentialBackOff(); HttpUnsuccessfulResponseHandler backoffHandler = new HttpBackOffUnsuccessfulResponseHandler(backoff) .setBackOffRequired(HttpBackOffUnsuccessfulResponseHandler.BackOffRequired.ALWAYS); httpRequest.setUnsuccessfulResponseHandler(backoffHandler); httpRequest.setConnectTimeout(connectTimeoutMs); httpRequest.setReadTimeout(readTimeoutMs); } }; }
@Override public boolean handleResponse(HttpRequest request, HttpResponse response, boolean supportsRetry) throws IOException { for (HttpUnsuccessfulResponseHandler handler : handlers) { if (handler.handleResponse(request, response, supportsRetry)) { return true; } } return false; }
/** * Returns a new {@link HttpUnsuccessfulResponseHandler} that runs all of * the given handlers in order until one of them returns {@code true}. * * @param handlers the handlers to run. Note that {@code null} values are * skipped. */ public HttpUnsuccessfulResponseHandler chain( HttpUnsuccessfulResponseHandler... handlers) { return (unsuccessfulRequest, response, supportsRetry) -> { boolean retry = false; for (int i = 0; i < handlers.length && !retry; i++) { if (handlers[i] != null) { retry = handlers[i].handleResponse( unsuccessfulRequest, response, supportsRetry); } } return retry; }; }
@Test public void testChainOfOne() throws Exception { HttpUnsuccessfulResponseHandler handler = mock(HttpUnsuccessfulResponseHandler.class); chainer.chain(handler) .handleResponse(httpRequest, httpResponse, SUPPORTS_RETRY); verify(handler) .handleResponse( any(HttpRequest.class), any(HttpResponse.class), any(Boolean.TYPE)); }
@Override public void initialize(HttpRequest request) throws IOException { List<HttpIOExceptionHandler> ioExceptionHandlers = new ArrayList<>(); List<HttpUnsuccessfulResponseHandler> unsuccessfulResponseHandlers = new ArrayList<>(); List<HttpExecuteInterceptor> interceptors = new ArrayList<>(); List<HttpResponseInterceptor> responseInterceptors = new ArrayList<>(); for (HttpRequestInitializer initializer : initializers) { initializer.initialize(request); if (request.getIOExceptionHandler() != null) { ioExceptionHandlers.add(request.getIOExceptionHandler()); request.setIOExceptionHandler(null); } if (request.getUnsuccessfulResponseHandler() != null) { unsuccessfulResponseHandlers.add(request.getUnsuccessfulResponseHandler()); request.setUnsuccessfulResponseHandler(null); } if (request.getInterceptor() != null) { interceptors.add(request.getInterceptor()); request.setInterceptor(null); } if (request.getResponseInterceptor() != null) { responseInterceptors.add(request.getResponseInterceptor()); request.setResponseInterceptor(null); } } request.setIOExceptionHandler( makeIoExceptionHandler(ioExceptionHandlers)); request.setUnsuccessfulResponseHandler( makeUnsuccessfulResponseHandler(unsuccessfulResponseHandlers)); request.setInterceptor( makeInterceptor(interceptors)); request.setResponseInterceptor( makeResponseInterceptor(responseInterceptors)); }
private HttpUnsuccessfulResponseHandler makeUnsuccessfulResponseHandler( final Iterable<HttpUnsuccessfulResponseHandler> unsuccessfulResponseHandlers) { return new HttpUnsuccessfulResponseHandler() { @Override public boolean handleResponse(HttpRequest request, HttpResponse response, boolean supportsRetry) throws IOException { for (HttpUnsuccessfulResponseHandler handler : unsuccessfulResponseHandlers) { if (handler.handleResponse(request, response, supportsRetry)) { return true; } } return false; } }; }
/** * @param delegateResponseHandler The HttpUnsuccessfulResponseHandler to invoke to * really handle errors. * @param delegateIOExceptionHandler The HttpIOExceptionResponseHandler to delegate to. * @param responseCodesToLog The set of response codes to log URLs for. */ public LoggingResponseHandler( HttpUnsuccessfulResponseHandler delegateResponseHandler, HttpIOExceptionHandler delegateIOExceptionHandler, Set<Integer> responseCodesToLog) { this.delegateResponseHandler = delegateResponseHandler; this.delegateIOExceptionHandler = delegateIOExceptionHandler; this.responseCodesToLog = ImmutableSet.copyOf(responseCodesToLog); }
@Override public void initialize(HttpRequest httpRequest) { final HttpUnsuccessfulResponseHandler backoffHandler = new HttpBackOffUnsuccessfulResponseHandler( new ExponentialBackOff.Builder() .setMaxElapsedTimeMillis(((int) maxWait.getMillis())) .build()) .setSleeper(sleeper); httpRequest.setInterceptor(wrappedCredential); httpRequest.setUnsuccessfulResponseHandler( new HttpUnsuccessfulResponseHandler() { int retry = 0; @Override public boolean handleResponse(HttpRequest request, HttpResponse response, boolean supportsRetry) throws IOException { if (wrappedCredential.handleResponse( request, response, supportsRetry)) { // If credential decides it can handle it, // the return code or message indicated // something specific to authentication, // and no backoff is desired. return true; } else if (backoffHandler.handleResponse( request, response, supportsRetry)) { // Otherwise, we defer to the judgement of // our internal backoff handler. logger.debug("Retrying [{}] times : [{}]", retry, request.getUrl()); return true; } else { return false; } } }); httpRequest.setIOExceptionHandler( new HttpBackOffIOExceptionHandler( new ExponentialBackOff.Builder() .setMaxElapsedTimeMillis(((int) maxWait.getMillis())) .build()) .setSleeper(sleeper) ); }
public CompositeHttpUnsuccessfulResponseHandler(HttpUnsuccessfulResponseHandler... handlers) { this.handlers = handlers; }
@Test public void testChainOfZero() throws Exception { HttpUnsuccessfulResponseHandler handler = chainer.chain(); handler.handleResponse(httpRequest, httpResponse, SUPPORTS_RETRY); }