externalized retry codes

This commit is contained in:
Adrian Cole 2012-09-12 21:35:41 -07:00
parent 80f6101e1f
commit a0b1ffb625
3 changed files with 36 additions and 10 deletions

View File

@ -20,6 +20,9 @@ package org.jclouds.aws.config;
import java.util.Map;
import java.util.Set;
import javax.inject.Singleton;
import org.jclouds.aws.handlers.AWSClientErrorRetryHandler;
import org.jclouds.aws.handlers.ParseAWSErrorFromXmlContent;
@ -31,7 +34,9 @@ import org.jclouds.http.annotation.ServerError;
import org.jclouds.rest.ConfiguresRestClient;
import org.jclouds.rest.config.RestClientModule;
import com.google.common.collect.ImmutableSet;
import com.google.common.reflect.TypeToken;
import com.google.inject.Provides;
/**
@ -57,6 +62,13 @@ public abstract class AWSRestClientModule<S, A> extends RestClientModule<S, A> {
super(syncClientType, asyncClientType, sync2Async);
}
@Provides
@ClientError
@Singleton
protected Set<String> provideRetryableCodes(){
return ImmutableSet.of("RequestTimeout", "OperationAborted", "SignatureDoesNotMatch");
}
@Override
protected void bindErrorHandlers() {
bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to(ParseAWSErrorFromXmlContent.class);

View File

@ -20,14 +20,16 @@ package org.jclouds.aws.handlers;
import static org.jclouds.http.HttpUtils.closeClientButKeepContentStream;
import java.util.Set;
import org.jclouds.aws.domain.AWSError;
import org.jclouds.aws.util.AWSUtils;
import org.jclouds.http.HttpCommand;
import org.jclouds.http.HttpResponse;
import org.jclouds.http.HttpRetryHandler;
import org.jclouds.http.annotation.ClientError;
import org.jclouds.http.handlers.BackoffLimitedRetryHandler;
import com.google.common.collect.ImmutableSet;
import com.google.inject.Inject;
/**
@ -39,27 +41,35 @@ public class AWSClientErrorRetryHandler implements HttpRetryHandler {
private final AWSUtils utils;
private final BackoffLimitedRetryHandler backoffLimitedRetryHandler;
private final Set<String> retryableCodes;
@Inject
public AWSClientErrorRetryHandler(AWSUtils utils, BackoffLimitedRetryHandler backoffLimitedRetryHandler) {
public AWSClientErrorRetryHandler(AWSUtils utils, BackoffLimitedRetryHandler backoffLimitedRetryHandler,
@ClientError Set<String> retryableCodes) {
this.utils = utils;
this.backoffLimitedRetryHandler = backoffLimitedRetryHandler;
this.retryableCodes = retryableCodes;
}
@Override
public boolean shouldRetryRequest(HttpCommand command, HttpResponse response) {
if (response.getStatusCode() == 400 || response.getStatusCode() == 403 || response.getStatusCode() == 409) {
// Content can be null in the case of HEAD requests
if (response.getPayload() != null) {
closeClientButKeepContentStream(response);
AWSError error = utils.parseAWSErrorFromContent(command.getCurrentRequest(), response);
if (error != null
&& ImmutableSet.of("RequestTimeout", "OperationAborted", "SignatureDoesNotMatch").contains(
error.getCode())) {
return backoffLimitedRetryHandler.shouldRetryRequest(command, response);
if (error != null) {
return shouldRetryRequestOnError(command, response, error);
}
}
}
return false;
}
protected boolean shouldRetryRequestOnError(HttpCommand command, HttpResponse response, AWSError error) {
if (retryableCodes.contains(error.getCode()))
return backoffLimitedRetryHandler.shouldRetryRequest(command, response);
return false;
}
}

View File

@ -33,6 +33,8 @@ import org.jclouds.io.Payloads;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableSet;
/**
* Tests behavior of {@code AWSClientErrorRetryHandler}
*
@ -49,7 +51,8 @@ public class AWSClientErrorRetryHandlerTest {
replay(utils, backoffLimitedRetryHandler, command);
AWSClientErrorRetryHandler retry = new AWSClientErrorRetryHandler(utils, backoffLimitedRetryHandler);
AWSClientErrorRetryHandler retry = new AWSClientErrorRetryHandler(utils, backoffLimitedRetryHandler,
ImmutableSet.<String> of());
assert !retry.shouldRetryRequest(command, HttpResponse.builder().statusCode(401).build());
@ -70,10 +73,10 @@ public class AWSClientErrorRetryHandlerTest {
HttpCommand command = createMock(HttpCommand.class);
HttpRequest putBucket = HttpRequest.builder().method("PUT")
.endpoint("https://adriancole-blobstore113.s3.amazonaws.com/").build();
.endpoint("https://adriancole-blobstore113.s3.amazonaws.com/").build();
HttpResponse operationAborted = HttpResponse.builder().statusCode(409)
.payload(Payloads.newStringPayload(String.format("<Error><Code>%s</Code></Error>", code))).build();
.payload(Payloads.newStringPayload(String.format("<Error><Code>%s</Code></Error>", code))).build();
expect(command.getCurrentRequest()).andReturn(putBucket);
@ -86,7 +89,8 @@ public class AWSClientErrorRetryHandlerTest {
replay(utils, backoffLimitedRetryHandler, command);
AWSClientErrorRetryHandler retry = new AWSClientErrorRetryHandler(utils, backoffLimitedRetryHandler);
AWSClientErrorRetryHandler retry = new AWSClientErrorRetryHandler(utils, backoffLimitedRetryHandler,
ImmutableSet.<String> of("RequestTimeout", "OperationAborted", "SignatureDoesNotMatch"));
assert retry.shouldRetryRequest(command, operationAborted);