Skip to content
This repository was archived by the owner on Sep 26, 2023. It is now read-only.

Commit 33fa52b

Browse files
authored
Retry and failure-handling logic for http-json (#363)
Exception handling and retry logic for http calls.
1 parent 5e4a386 commit 33fa52b

7 files changed

Lines changed: 389 additions & 39 deletions

File tree

gax-grpc/src/test/java/com/google/api/gax/grpc/CancellationTest.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import com.google.api.core.ApiFuture;
3434
import com.google.api.core.SettableApiFuture;
3535
import com.google.api.gax.core.FakeApiClock;
36+
import com.google.api.gax.core.RecordingScheduler;
3637
import com.google.api.gax.retrying.RetrySettings;
3738
import com.google.api.gax.rpc.ApiCallContext;
3839
import com.google.api.gax.rpc.ClientContext;

gax-grpc/src/test/java/com/google/api/gax/grpc/GrpcOperationCallableImplTest.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
import com.google.api.core.ApiFuture;
3939
import com.google.api.core.ListenableFutureToApiFuture;
4040
import com.google.api.gax.core.FakeApiClock;
41+
import com.google.api.gax.core.RecordingScheduler;
4142
import com.google.api.gax.grpc.testing.FakeMethodDescriptor;
4243
import com.google.api.gax.retrying.RetrySettings;
4344
import com.google.api.gax.retrying.TimedAttemptSettings;

gax-grpc/src/test/java/com/google/api/gax/grpc/RetryingTest.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import com.google.api.core.ApiFuture;
3333
import com.google.api.core.ApiFutures;
3434
import com.google.api.gax.core.FakeApiClock;
35+
import com.google.api.gax.core.RecordingScheduler;
3536
import com.google.api.gax.retrying.RetrySettings;
3637
import com.google.api.gax.rpc.ApiCallContext;
3738
import com.google.api.gax.rpc.ApiException;
@@ -133,7 +134,7 @@ public void retryTotalTimeoutExceeded() {
133134
}
134135

135136
@Test(expected = ApiException.class)
136-
public void retryMaxAttemptsExeeded() {
137+
public void retryMaxAttemptsExceeded() {
137138
ImmutableSet<StatusCode> retryable =
138139
ImmutableSet.<StatusCode>of(GrpcStatusCode.of(Status.Code.UNAVAILABLE));
139140
Throwable throwable = Status.UNAVAILABLE.asException();

gax-httpjson/src/main/java/com/google/api/gax/httpjson/ApiResultRetryAlgorithm.java

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -31,27 +31,30 @@
3131

3232
import com.google.api.gax.retrying.ResultRetryAlgorithm;
3333
import com.google.api.gax.retrying.TimedAttemptSettings;
34+
import com.google.api.gax.rpc.StatusCode;
3435
import org.threeten.bp.Duration;
3536

3637
/* Package-private for internal use. */
3738
class ApiResultRetryAlgorithm<ResponseT> implements ResultRetryAlgorithm<ResponseT> {
3839
// Duration to sleep on if the error is DEADLINE_EXCEEDED.
39-
public static final Duration DEADLINE_SLEEP_DURATION = Duration.ofMillis(1);
40+
static final Duration DEADLINE_SLEEP_DURATION = Duration.ofMillis(1);
41+
42+
public static final int STATUS_CODE_DEADLINE_EXCEEDED = 504;
4043

4144
@Override
4245
public TimedAttemptSettings createNextAttempt(
4346
Throwable prevThrowable, ResponseT prevResponse, TimedAttemptSettings prevSettings) {
44-
// TODO figure out the right http code
45-
// if (prevThrowable != null
46-
// && ((HttpJsonApiException) prevThrowable).getStatusCode().getCode() == Code.DEADLINE_EXCEEDED) {
47-
// return new TimedAttemptSettings(
48-
// prevSettings.getGlobalSettings(),
49-
// prevSettings.getRetryDelay(),
50-
// prevSettings.getRpcTimeout(),
51-
// DEADLINE_SLEEP_DURATION,
52-
// prevSettings.getAttemptCount() + 1,
53-
// prevSettings.getFirstAttemptStartTimeNanos());
54-
// }
47+
StatusCode responseCode = ((HttpJsonApiException) prevThrowable).getStatusCode();
48+
if (prevThrowable != null
49+
&& responseCode.equals(HttpJsonStatusCode.of(STATUS_CODE_DEADLINE_EXCEEDED))) {
50+
return new TimedAttemptSettings(
51+
prevSettings.getGlobalSettings(),
52+
prevSettings.getRetryDelay(),
53+
prevSettings.getRpcTimeout(),
54+
DEADLINE_SLEEP_DURATION,
55+
prevSettings.getAttemptCount() + 1,
56+
prevSettings.getFirstAttemptStartTimeNanos());
57+
}
5558
return null;
5659
}
5760

gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpJsonExceptionCallable.java

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929
*/
3030
package com.google.api.gax.httpjson;
3131

32+
import com.google.api.client.http.HttpResponseException;
33+
import com.google.api.client.http.HttpStatusCodes;
3234
import com.google.api.core.AbstractApiFuture;
3335
import com.google.api.core.ApiFuture;
3436
import com.google.api.core.ApiFutureCallback;
@@ -88,26 +90,25 @@ public void onSuccess(ResponseT r) {
8890

8991
@Override
9092
public void onFailure(Throwable throwable) {
91-
int statusCode = 0;
92-
boolean canRetry = true;
93-
// TODO implement this for http-json
94-
// if (throwable instanceof StatusException) {
95-
// StatusException e = (StatusException) throwable;
96-
// statusCode = e.getStatus().getCode();
97-
// canRetry = retryableCodes.contains(statusCode);
98-
// } else if (throwable instanceof StatusRuntimeException) {
99-
// StatusRuntimeException e = (StatusRuntimeException) throwable;
100-
// statusCode = e.getStatus().getCode();
101-
// canRetry = retryableCodes.contains(statusCode);
102-
// } else if (throwable instanceof CancellationException && cancelled) {
103-
// // this just circled around, so ignore.
104-
// return;
105-
// } else {
106-
// // Do not retry on unknown throwable, even when UNKNOWN is in retryableCodes
107-
// statusCode = Status.Code.UNKNOWN;
108-
// canRetry = false;
109-
// }
110-
super.setException(new HttpJsonApiException(throwable, statusCode, canRetry));
93+
int statusCode;
94+
boolean canRetry;
95+
String message = null;
96+
if (throwable instanceof HttpResponseException) {
97+
HttpResponseException e = (HttpResponseException) throwable;
98+
statusCode = e.getStatusCode();
99+
canRetry = retryableCodes.contains(statusCode);
100+
message = e.getStatusMessage();
101+
} else {
102+
// Do not retry on unknown throwable, even when UNKNOWN is in retryableCodes
103+
statusCode = HttpStatusCodes.STATUS_CODE_SERVER_ERROR;
104+
canRetry = false;
105+
}
106+
107+
HttpJsonApiException exception =
108+
message == null
109+
? new HttpJsonApiException(throwable, statusCode, canRetry)
110+
: new HttpJsonApiException(message, throwable, statusCode, canRetry);
111+
super.setException(exception);
111112
}
112113
}
113114
}

0 commit comments

Comments
 (0)