@Test public void retries_for_listed_exceptions_until_max_retries_exceeded() { int maxRetries = 2; DelayedConnectionLevelRetryHandler handler = DelayedConnectionLevelRetryHandler.Builder .withFixedDelay(Duration.ofSeconds(2), maxRetries) .retryForExceptions(List.of(SSLException.class, ConnectException.class)) .withSleeper(mock(Sleeper.class)) .build(); SSLException sslException = new SSLException("ssl error"); HttpClientContext ctx = new HttpClientContext(); int lastExecutionCount = maxRetries + 1; for (int i = 1; i < lastExecutionCount; i++) { assertTrue(handler.retryRequest(sslException, i, ctx)); } assertFalse(handler.retryRequest(sslException, lastExecutionCount, ctx)); }
@Override public boolean retryRequest(IOException exception, int executionCount, HttpContext ctx) { log.fine(() -> String.format("retryRequest(exception='%s', executionCount='%d', ctx='%s'", exception.getClass().getName(), executionCount, ctx)); HttpClientContext clientCtx = HttpClientContext.adapt(ctx); if (!predicate.test(exception, clientCtx)) { log.fine(() -> String.format("Not retrying for '%s'", ctx)); return false; } if (executionCount > maxRetries) { log.fine(() -> String.format("Max retries exceeded for '%s'", ctx)); retryFailedConsumer.onRetryFailed(exception, executionCount, clientCtx); return false; } Duration delay = delaySupplier.getDelay(executionCount); log.fine(() -> String.format("Retrying after %s for '%s'", delay, ctx)); retryConsumer.onRetry(exception, delay, executionCount, clientCtx); sleeper.sleep(delay); return true; }
DelayedConnectionLevelRetryHandler implements HttpRequestRetryHandler { @Override public boolean retryRequest(IOException exception, int executionCount, HttpContext ctx) { log.fine(() -> String.format("retryRequest(exception='%s', executionCount='%d', ctx='%s'", exception.getClass().getName(), executionCount, ctx)); HttpClientContext clientCtx = HttpClientContext.adapt(ctx); if (!predicate.test(exception, clientCtx)) { log.fine(() -> String.format("Not retrying for '%s'", ctx)); return false; } if (executionCount > maxRetries) { log.fine(() -> String.format("Max retries exceeded for '%s'", ctx)); retryFailedConsumer.onRetryFailed(exception, executionCount, clientCtx); return false; } Duration delay = delaySupplier.getDelay(executionCount); log.fine(() -> String.format("Retrying after %s for '%s'", delay, ctx)); retryConsumer.onRetry(exception, delay, executionCount, clientCtx); sleeper.sleep(delay); return true; } }
DelayedConnectionLevelRetryHandler implements HttpRequestRetryHandler { @Override public boolean retryRequest(IOException exception, int executionCount, HttpContext ctx) { log.fine(() -> String.format("retryRequest(exception='%s', executionCount='%d', ctx='%s'", exception.getClass().getName(), executionCount, ctx)); HttpClientContext clientCtx = HttpClientContext.adapt(ctx); if (!predicate.test(exception, clientCtx)) { log.fine(() -> String.format("Not retrying for '%s'", ctx)); return false; } if (executionCount > maxRetries) { log.fine(() -> String.format("Max retries exceeded for '%s'", ctx)); retryFailedConsumer.onRetryFailed(exception, executionCount, clientCtx); return false; } Duration delay = delaySupplier.getDelay(executionCount); log.fine(() -> String.format("Retrying after %s for '%s'", delay, ctx)); retryConsumer.onRetry(exception, delay, executionCount, clientCtx); sleeper.sleep(delay); return true; } private  DelayedConnectionLevelRetryHandler(
            DelaySupplier delaySupplier,
            int maxRetries,
            RetryPredicate<IOException> predicate,
            RetryConsumer<IOException> retryConsumer,
            RetryFailedConsumer<IOException> retryFailedConsumer,
            Sleeper sleeper); }
DelayedConnectionLevelRetryHandler implements HttpRequestRetryHandler { @Override public boolean retryRequest(IOException exception, int executionCount, HttpContext ctx) { log.fine(() -> String.format("retryRequest(exception='%s', executionCount='%d', ctx='%s'", exception.getClass().getName(), executionCount, ctx)); HttpClientContext clientCtx = HttpClientContext.adapt(ctx); if (!predicate.test(exception, clientCtx)) { log.fine(() -> String.format("Not retrying for '%s'", ctx)); return false; } if (executionCount > maxRetries) { log.fine(() -> String.format("Max retries exceeded for '%s'", ctx)); retryFailedConsumer.onRetryFailed(exception, executionCount, clientCtx); return false; } Duration delay = delaySupplier.getDelay(executionCount); log.fine(() -> String.format("Retrying after %s for '%s'", delay, ctx)); retryConsumer.onRetry(exception, delay, executionCount, clientCtx); sleeper.sleep(delay); return true; } private  DelayedConnectionLevelRetryHandler(
            DelaySupplier delaySupplier,
            int maxRetries,
            RetryPredicate<IOException> predicate,
            RetryConsumer<IOException> retryConsumer,
            RetryFailedConsumer<IOException> retryFailedConsumer,
            Sleeper sleeper); @Override boolean retryRequest(IOException exception, int executionCount, HttpContext ctx); }
DelayedConnectionLevelRetryHandler implements HttpRequestRetryHandler { @Override public boolean retryRequest(IOException exception, int executionCount, HttpContext ctx) { log.fine(() -> String.format("retryRequest(exception='%s', executionCount='%d', ctx='%s'", exception.getClass().getName(), executionCount, ctx)); HttpClientContext clientCtx = HttpClientContext.adapt(ctx); if (!predicate.test(exception, clientCtx)) { log.fine(() -> String.format("Not retrying for '%s'", ctx)); return false; } if (executionCount > maxRetries) { log.fine(() -> String.format("Max retries exceeded for '%s'", ctx)); retryFailedConsumer.onRetryFailed(exception, executionCount, clientCtx); return false; } Duration delay = delaySupplier.getDelay(executionCount); log.fine(() -> String.format("Retrying after %s for '%s'", delay, ctx)); retryConsumer.onRetry(exception, delay, executionCount, clientCtx); sleeper.sleep(delay); return true; } private  DelayedConnectionLevelRetryHandler(
            DelaySupplier delaySupplier,
            int maxRetries,
            RetryPredicate<IOException> predicate,
            RetryConsumer<IOException> retryConsumer,
            RetryFailedConsumer<IOException> retryFailedConsumer,
            Sleeper sleeper); @Override boolean retryRequest(IOException exception, int executionCount, HttpContext ctx);  }