HTTPCLIENT-2080: add getRetryInterval to HttpRequestRetryStrategy for use on retriable IOExceptions (#356)
This commit is contained in:
parent
c395aad5ad
commit
94017237b2
|
@ -75,6 +75,22 @@ public interface HttpRequestRetryStrategy {
|
|||
*/
|
||||
boolean retryRequest(HttpResponse response, int execCount, HttpContext context);
|
||||
|
||||
|
||||
/**
|
||||
* Determines the retry interval between subsequent retries.
|
||||
*
|
||||
* @param request the request failed due to an I/O exception
|
||||
* @param exception the exception that occurred
|
||||
* @param execCount the number of times this method has been
|
||||
* unsuccessfully executed
|
||||
* @param context the context for the request execution
|
||||
*
|
||||
* @return the retry interval between subsequent retries
|
||||
*/
|
||||
default TimeValue getRetryInterval(HttpRequest request, IOException exception, int execCount, HttpContext context) {
|
||||
return TimeValue.ZERO_MILLISECONDS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the retry interval between subsequent retries.
|
||||
*
|
||||
|
|
|
@ -159,7 +159,8 @@ public final class AsyncHttpRequestRetryExec implements AsyncExecChainHandler {
|
|||
entityProducer.releaseResources();
|
||||
}
|
||||
state.retrying = true;
|
||||
scope.execCount.incrementAndGet();
|
||||
final int execCount = scope.execCount.incrementAndGet();
|
||||
state.delay = retryStrategy.getRetryInterval(request, (IOException) cause, execCount - 1, clientContext);
|
||||
scope.scheduler.scheduleExecution(request, entityProducer, scope, asyncExecCallback, state.delay);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -113,6 +113,18 @@ public class HttpRequestRetryExec implements ExecChainHandler {
|
|||
LOG.info("Recoverable I/O exception ({}) caught when processing request to {}",
|
||||
ex.getClass().getName(), route);
|
||||
}
|
||||
final TimeValue nextInterval = retryStrategy.getRetryInterval(request, ex, execCount, context);
|
||||
if (TimeValue.isPositive(nextInterval)) {
|
||||
try {
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("{} wait for {}", exchangeId, nextInterval);
|
||||
}
|
||||
nextInterval.sleep();
|
||||
} catch (final InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
throw new InterruptedIOException();
|
||||
}
|
||||
}
|
||||
currentRequest = ClassicRequestBuilder.copy(scope.originalRequest).build();
|
||||
continue;
|
||||
} else {
|
||||
|
|
|
@ -62,6 +62,8 @@ public class TestHttpRequestRetryExec {
|
|||
private ExecChain chain;
|
||||
@Mock
|
||||
private ExecRuntime endpoint;
|
||||
@Mock
|
||||
private TimeValue nextInterval;
|
||||
|
||||
private HttpRequestRetryExec retryExec;
|
||||
private HttpHost target;
|
||||
|
@ -103,6 +105,39 @@ public class TestHttpRequestRetryExec {
|
|||
Mockito.verify(response, Mockito.times(1)).close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRetrySleepOnIOException() throws Exception {
|
||||
final HttpRoute route = new HttpRoute(target);
|
||||
final HttpGet request = new HttpGet("/test");
|
||||
final HttpClientContext context = HttpClientContext.create();
|
||||
|
||||
final ClassicHttpResponse response = Mockito.mock(ClassicHttpResponse.class);
|
||||
|
||||
Mockito.when(chain.proceed(
|
||||
Mockito.same(request),
|
||||
Mockito.any())).thenThrow(new IOException("Ka-boom"));
|
||||
Mockito.when(retryStrategy.retryRequest(
|
||||
Mockito.any(),
|
||||
Mockito.any(),
|
||||
Mockito.anyInt(),
|
||||
Mockito.any())).thenReturn(Boolean.TRUE, Boolean.FALSE);
|
||||
Mockito.when(retryStrategy.getRetryInterval(
|
||||
Mockito.any(),
|
||||
Mockito.any(),
|
||||
Mockito.anyInt(),
|
||||
Mockito.any())).thenReturn(nextInterval);
|
||||
Mockito.when(nextInterval.getDuration()).thenReturn(100L);
|
||||
Mockito.when(nextInterval.compareTo(Mockito.any())).thenReturn(-1);
|
||||
|
||||
final ExecChain.Scope scope = new ExecChain.Scope("test", route, request, endpoint, context);
|
||||
retryExec.execute(request, scope, chain);
|
||||
|
||||
Mockito.verify(chain, Mockito.times(2)).proceed(
|
||||
Mockito.any(),
|
||||
Mockito.same(scope));
|
||||
Mockito.verify(nextInterval, Mockito.times(1)).sleep();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRetryIntervalGreaterResponseTimeout() throws Exception {
|
||||
final HttpRoute route = new HttpRoute(target);
|
||||
|
|
Loading…
Reference in New Issue