Repository: jclouds-labs Updated Branches: refs/heads/master 88ef0a221 -> d812c9d83
JCLOUDS-1005: Retry on 500 and 503 errors This requires rewriting the URL for b2_upload_file and b2_upload_part requests. Project: http://git-wip-us.apache.org/repos/asf/jclouds-labs/repo Commit: http://git-wip-us.apache.org/repos/asf/jclouds-labs/commit/d812c9d8 Tree: http://git-wip-us.apache.org/repos/asf/jclouds-labs/tree/d812c9d8 Diff: http://git-wip-us.apache.org/repos/asf/jclouds-labs/diff/d812c9d8 Branch: refs/heads/master Commit: d812c9d833a82dd74c8631d4bf68663a6fd2a897 Parents: 88ef0a2 Author: Andrew Gaul <[email protected]> Authored: Tue Jun 14 21:35:19 2016 -0700 Committer: Andrew Gaul <[email protected]> Committed: Tue Jun 21 18:12:36 2016 -0700 ---------------------------------------------------------------------- .../main/java/org/jclouds/b2/B2ApiMetadata.java | 2 + .../org/jclouds/b2/config/B2HttpApiModule.java | 7 ++ .../org/jclouds/b2/filters/B2RetryHandler.java | 90 ++++++++++++++++++++ 3 files changed, 99 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/d812c9d8/b2/src/main/java/org/jclouds/b2/B2ApiMetadata.java ---------------------------------------------------------------------- diff --git a/b2/src/main/java/org/jclouds/b2/B2ApiMetadata.java b/b2/src/main/java/org/jclouds/b2/B2ApiMetadata.java index ef2e715..b5aecaa 100644 --- a/b2/src/main/java/org/jclouds/b2/B2ApiMetadata.java +++ b/b2/src/main/java/org/jclouds/b2/B2ApiMetadata.java @@ -48,6 +48,8 @@ public final class B2ApiMetadata extends BaseHttpApiMetadata { public static Properties defaultProperties() { Properties properties = BaseHttpApiMetadata.defaultProperties(); properties.setProperty(Constants.PROPERTY_SESSION_INTERVAL, String.valueOf(TimeUnit.HOURS.toSeconds(1))); + properties.setProperty(Constants.PROPERTY_IDEMPOTENT_METHODS, "DELETE,GET,HEAD,OPTIONS,POST,PUT"); + properties.setProperty(Constants.PROPERTY_RETRY_DELAY_START, String.valueOf(TimeUnit.SECONDS.toMillis(1))); return properties; } http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/d812c9d8/b2/src/main/java/org/jclouds/b2/config/B2HttpApiModule.java ---------------------------------------------------------------------- diff --git a/b2/src/main/java/org/jclouds/b2/config/B2HttpApiModule.java b/b2/src/main/java/org/jclouds/b2/config/B2HttpApiModule.java index 11d8624..a30f9a4 100644 --- a/b2/src/main/java/org/jclouds/b2/config/B2HttpApiModule.java +++ b/b2/src/main/java/org/jclouds/b2/config/B2HttpApiModule.java @@ -26,9 +26,11 @@ import org.jclouds.Constants; import org.jclouds.collect.Memoized; import org.jclouds.b2.B2Api; import org.jclouds.b2.domain.Authorization; +import org.jclouds.b2.filters.B2RetryHandler; import org.jclouds.b2.filters.RequestAuthorization; import org.jclouds.b2.handlers.ParseB2ErrorFromJsonContent; import org.jclouds.http.HttpErrorHandler; +import org.jclouds.http.HttpRetryHandler; import org.jclouds.http.annotation.ClientError; import org.jclouds.http.annotation.Redirection; import org.jclouds.http.annotation.ServerError; @@ -57,6 +59,11 @@ public final class B2HttpApiModule extends HttpApiModule<B2Api> { bind(HttpErrorHandler.class).annotatedWith(ServerError.class).to(ParseB2ErrorFromJsonContent.class); } + @Override + protected void bindRetryHandlers() { + bind(HttpRetryHandler.class).annotatedWith(ServerError.class).to(B2RetryHandler.class); + } + @Provides @Singleton static Supplier<Authorization> provideAuthorizationSupplier(final B2Api b2Api) { http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/d812c9d8/b2/src/main/java/org/jclouds/b2/filters/B2RetryHandler.java ---------------------------------------------------------------------- diff --git a/b2/src/main/java/org/jclouds/b2/filters/B2RetryHandler.java b/b2/src/main/java/org/jclouds/b2/filters/B2RetryHandler.java new file mode 100644 index 0000000..e58d712 --- /dev/null +++ b/b2/src/main/java/org/jclouds/b2/filters/B2RetryHandler.java @@ -0,0 +1,90 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.b2.filters; + +import static org.jclouds.http.HttpUtils.closeClientButKeepContentStream; +import static org.jclouds.http.HttpUtils.releasePayload; + +import javax.annotation.Resource; +import javax.inject.Inject; + +import org.jclouds.b2.B2Api; +import org.jclouds.b2.domain.GetUploadPartResponse; +import org.jclouds.b2.domain.UploadUrlResponse; +import org.jclouds.http.HttpCommand; +import org.jclouds.http.HttpException; +import org.jclouds.http.HttpRequest; +import org.jclouds.http.HttpRequestFilter; +import org.jclouds.http.HttpResponse; +import org.jclouds.http.handlers.BackoffLimitedRetryHandler; +import org.jclouds.logging.Logger; + +import com.google.common.net.HttpHeaders; +import com.google.inject.Singleton; + +@Singleton +public final class B2RetryHandler extends BackoffLimitedRetryHandler implements HttpRequestFilter { + private final B2Api api; + + @Resource + private Logger logger = Logger.NULL; + + @Inject + B2RetryHandler(B2Api api) { + this.api = api; + } + + @Override + public HttpRequest filter(HttpRequest request) throws HttpException { + HttpRequest.Builder<?> builder = request.toBuilder(); + + // B2 requires retrying on a different storage node for uploads + String path = request.getEndpoint().getPath(); + if (path.startsWith("/b2api/v1/b2_upload_file")) { + String bucketId = path.split("/")[4]; + UploadUrlResponse uploadUrl = api.getObjectApi().getUploadUrl(bucketId); + builder.endpoint(uploadUrl.uploadUrl()) + .replaceHeader(HttpHeaders.AUTHORIZATION, uploadUrl.authorizationToken()); + } else if (path.startsWith("/b2api/v1/b2_upload_part")) { + String fileId = path.split("/")[4]; + GetUploadPartResponse uploadUrl = api.getMultipartApi().getUploadPartUrl(fileId); + builder.endpoint(uploadUrl.uploadUrl()) + .replaceHeader(HttpHeaders.AUTHORIZATION, uploadUrl.authorizationToken()); + } + + return builder.build(); + } + + @Override + public boolean shouldRetryRequest(HttpCommand command, HttpResponse response) { + boolean retry = false; + try { + byte[] data = closeClientButKeepContentStream(response); + switch (response.getStatusCode()) { + case 500: + case 503: + retry = super.shouldRetryRequest(command, response); + break; + default: + break; + } + } finally { + releasePayload(response); + } + return retry; + } +}
