Repository: jclouds Updated Branches: refs/heads/1.7.x 08992c7a3 -> c368bae28
JCLOUDS-342: Retry on HTTP 408 for swift To repro issue 342, the following steps were taken: - Spawn 500 parallel / 2000 total putBlobs to cloudfiles-uk - issue a SIGSTOP - wait 60 seconds - issue a SIGCONT Without this patch, there are several hundred 408s. With this patch, these are retried and complete successfully. Project: http://git-wip-us.apache.org/repos/asf/jclouds/repo Commit: http://git-wip-us.apache.org/repos/asf/jclouds/commit/c368bae2 Tree: http://git-wip-us.apache.org/repos/asf/jclouds/tree/c368bae2 Diff: http://git-wip-us.apache.org/repos/asf/jclouds/diff/c368bae2 Branch: refs/heads/1.7.x Commit: c368bae28c841c34252cdafe2d42145c65ead2f7 Parents: 08992c7 Author: Tom Manville <[email protected]> Authored: Wed Feb 26 13:28:20 2014 -0800 Committer: Andrew Gaul <[email protected]> Committed: Mon Mar 3 16:48:19 2014 -0800 ---------------------------------------------------------------------- .../keystone/v1_1/handlers/RetryOnRenew.java | 15 ++++- .../v1_1/handlers/RetryOnRenewTest.java | 62 +++++++++++++++++++- 2 files changed, 75 insertions(+), 2 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/jclouds/blob/c368bae2/common/openstack/src/main/java/org/jclouds/openstack/keystone/v1_1/handlers/RetryOnRenew.java ---------------------------------------------------------------------- diff --git a/common/openstack/src/main/java/org/jclouds/openstack/keystone/v1_1/handlers/RetryOnRenew.java b/common/openstack/src/main/java/org/jclouds/openstack/keystone/v1_1/handlers/RetryOnRenew.java index fe8309d..a9446fe 100644 --- a/common/openstack/src/main/java/org/jclouds/openstack/keystone/v1_1/handlers/RetryOnRenew.java +++ b/common/openstack/src/main/java/org/jclouds/openstack/keystone/v1_1/handlers/RetryOnRenew.java @@ -20,11 +20,14 @@ import static org.jclouds.http.HttpUtils.closeClientButKeepContentStream; import static org.jclouds.http.HttpUtils.releasePayload; import javax.annotation.Resource; +import javax.inject.Named; +import org.jclouds.Constants; import org.jclouds.domain.Credentials; import org.jclouds.http.HttpCommand; import org.jclouds.http.HttpResponse; import org.jclouds.http.HttpRetryHandler; +import org.jclouds.http.handlers.BackoffLimitedRetryHandler; import org.jclouds.logging.Logger; import org.jclouds.openstack.keystone.v1_1.domain.Auth; import org.jclouds.openstack.reference.AuthHeaders; @@ -42,14 +45,22 @@ import com.google.inject.Singleton; */ @Singleton public class RetryOnRenew implements HttpRetryHandler { + @Inject(optional = true) + @Named(Constants.PROPERTY_MAX_RETRIES) + private int retryCountLimit = 5; + @Resource protected Logger logger = Logger.NULL; private final LoadingCache<Credentials, Auth> authenticationResponseCache; + private final BackoffLimitedRetryHandler backoffHandler; + @Inject - protected RetryOnRenew(LoadingCache<Credentials, Auth> authenticationResponseCache) { + protected RetryOnRenew(LoadingCache<Credentials, Auth> authenticationResponseCache, + BackoffLimitedRetryHandler backoffHandler) { this.authenticationResponseCache = authenticationResponseCache; + this.backoffHandler = backoffHandler; } @Override @@ -74,6 +85,8 @@ public class RetryOnRenew implements HttpRetryHandler { } } break; + case 408: + return backoffHandler.shouldRetryRequest(command, response); } return retry; http://git-wip-us.apache.org/repos/asf/jclouds/blob/c368bae2/common/openstack/src/test/java/org/jclouds/openstack/keystone/v1_1/handlers/RetryOnRenewTest.java ---------------------------------------------------------------------- diff --git a/common/openstack/src/test/java/org/jclouds/openstack/keystone/v1_1/handlers/RetryOnRenewTest.java b/common/openstack/src/test/java/org/jclouds/openstack/keystone/v1_1/handlers/RetryOnRenewTest.java index 59b4500..b68c8f1 100644 --- a/common/openstack/src/test/java/org/jclouds/openstack/keystone/v1_1/handlers/RetryOnRenewTest.java +++ b/common/openstack/src/test/java/org/jclouds/openstack/keystone/v1_1/handlers/RetryOnRenewTest.java @@ -27,6 +27,7 @@ import org.jclouds.domain.Credentials; import org.jclouds.http.HttpCommand; import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpResponse; +import org.jclouds.http.handlers.BackoffLimitedRetryHandler; import org.jclouds.io.Payloads; import org.jclouds.openstack.keystone.v1_1.domain.Auth; import org.testng.annotations.Test; @@ -47,6 +48,7 @@ public class RetryOnRenewTest { HttpResponse response = createMock(HttpResponse.class); @SuppressWarnings("unchecked") LoadingCache<Credentials, Auth> cache = createMock(LoadingCache.class); + BackoffLimitedRetryHandler backoffHandler = createMock(BackoffLimitedRetryHandler.class); expect(command.getCurrentRequest()).andReturn(request); @@ -59,13 +61,71 @@ public class RetryOnRenewTest { replay(command); replay(response); replay(cache); + replay(backoffHandler); - RetryOnRenew retry = new RetryOnRenew(cache); + RetryOnRenew retry = new RetryOnRenew(cache, backoffHandler); assertTrue(retry.shouldRetryRequest(command, response)); verify(command); verify(response); verify(cache); + verify(backoffHandler); + } + + @Test + public void test408ShouldRetry() { + HttpCommand command = createMock(HttpCommand.class); + HttpRequest request = createMock(HttpRequest.class); + HttpResponse response = createMock(HttpResponse.class); + @SuppressWarnings("unchecked") + LoadingCache<Credentials, Auth> cache = createMock(LoadingCache.class); + BackoffLimitedRetryHandler backoffHandler = createMock(BackoffLimitedRetryHandler.class); + + expect(response.getPayload()).andReturn(Payloads.newStringPayload( + "The server has waited too long for the request to be sent by the client.")).times(2); + expect(backoffHandler.shouldRetryRequest(command, response)).andReturn(true).once(); + expect(response.getStatusCode()).andReturn(408).once(); + + replay(command); + replay(response); + replay(cache); + replay(backoffHandler); + + RetryOnRenew retry = new RetryOnRenew(cache, backoffHandler); + + assertTrue(retry.shouldRetryRequest(command, response)); + + verify(command); + verify(response); + verify(cache); + verify(backoffHandler); + } + + @Test + public void test404ShouldNotRetry() { + HttpCommand command = createMock(HttpCommand.class); + HttpRequest request = createMock(HttpRequest.class); + HttpResponse response = createMock(HttpResponse.class); + @SuppressWarnings("unchecked") + LoadingCache<Credentials, Auth> cache = createMock(LoadingCache.class); + BackoffLimitedRetryHandler backoffHandler = createMock(BackoffLimitedRetryHandler.class); + + expect(response.getPayload()).andReturn(Payloads.newStringPayload("")).times(2); + expect(response.getStatusCode()).andReturn(404).once(); + + replay(command); + replay(response); + replay(cache); + replay(backoffHandler); + + RetryOnRenew retry = new RetryOnRenew(cache, backoffHandler); + + assertTrue(!retry.shouldRetryRequest(command, response)); + + verify(command); + verify(response); + verify(cache); + verify(backoffHandler); } }
