Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add AttemptCount to HttpResponseException #1505

Merged
merged 3 commits into from Nov 23, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -1113,7 +1113,9 @@ public HttpResponse execute() throws IOException {
// throw an exception if unsuccessful response
if (throwExceptionOnExecuteError && !response.isSuccessStatusCode()) {
try {
throw new HttpResponseException(response);
throw new HttpResponseException.Builder(response)
.setAttemptCount(numRetries - retriesRemaining)
.build();
} finally {
response.disconnect();
}
Expand Down
Expand Up @@ -42,6 +42,9 @@ public class HttpResponseException extends IOException {
/** HTTP response content or {@code null} for none. */
private final String content;

/** Number of attempts performed */
private final int attemptCount;

/**
* Constructor that constructs a detail message from the given HTTP response that includes the
* status code, status message and HTTP response content.
Expand Down Expand Up @@ -73,6 +76,7 @@ protected HttpResponseException(Builder builder) {
statusMessage = builder.statusMessage;
headers = builder.headers;
content = builder.content;
attemptCount = builder.attemptCount;
}

/**
Expand Down Expand Up @@ -121,6 +125,15 @@ public final String getContent() {
return content;
}

/**
* Returns the attempt count
*
* @since 1.41
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure if i need to add this manually

*/
public final int getAttemptCount() {
return attemptCount;
}

/**
* Builder.
*
Expand All @@ -145,6 +158,9 @@ public static class Builder {
/** Detail message to use or {@code null} for none. */
String message;

/** Number of attempts performed */
int attemptCount;

/**
* @param statusCode HTTP status code
* @param statusMessage status message or {@code null}
Expand Down Expand Up @@ -260,6 +276,18 @@ public Builder setContent(String content) {
return this;
}

/** Returns the request attempt count */
public final int getAttemptCount() {
return attemptCount;
}

/** Sets the attempt count for the related HTTP request execution. */
public Builder setAttemptCount(int attemptCount) {
Preconditions.checkArgument(attemptCount >= 0);
this.attemptCount = attemptCount;
return this;
}

/** Returns a new instance of {@link HttpResponseException} based on this builder. */
public HttpResponseException build() {
return new HttpResponseException(this);
Expand Down
Expand Up @@ -23,13 +23,15 @@
import com.google.api.client.testing.http.MockHttpTransport;
import com.google.api.client.testing.http.MockLowLevelHttpRequest;
import com.google.api.client.testing.http.MockLowLevelHttpResponse;
import com.google.api.client.util.ExponentialBackOff;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
import junit.framework.TestCase;
import org.junit.Assert;
import org.junit.function.ThrowingRunnable;

/**
Expand Down Expand Up @@ -208,6 +210,8 @@ public void run() throws Throwable {
+ SIMPLE_GENERIC_URL
+ LINE_SEPARATOR
+ "Unable to find resource");
// no retries expected
assertEquals(1, responseException.getAttemptCount());
}

public void testInvalidCharset() throws Exception {
Expand Down Expand Up @@ -245,6 +249,50 @@ public void run() throws Throwable {
.isEqualTo("404 Not Found\nGET " + SIMPLE_GENERIC_URL);
}

public void testAttemptCountWithBackOff() throws Exception {
HttpTransport fakeTransport =
new MockHttpTransport() {
@Override
public LowLevelHttpRequest buildRequest(String method, String url) throws IOException {
return new MockLowLevelHttpRequest() {
@Override
public LowLevelHttpResponse execute() throws IOException {
MockLowLevelHttpResponse result = new MockLowLevelHttpResponse();
result.setStatusCode(HttpStatusCodes.STATUS_CODE_SERVER_ERROR);
result.setReasonPhrase("Error");
result.setContent("Unknown Error");
return result;
}
};
}
};
ExponentialBackOff backoff = new ExponentialBackOff.Builder().build();
final HttpRequest request =
fakeTransport.createRequestFactory().buildGetRequest(new GenericUrl("http://not/used"));
request.setUnsuccessfulResponseHandler(
new HttpBackOffUnsuccessfulResponseHandler(backoff)
.setBackOffRequired(
new HttpBackOffUnsuccessfulResponseHandler.BackOffRequired() {
public boolean isRequired(HttpResponse response) {
return true;
}
}));
request.setNumberOfRetries(1);
HttpResponseException responseException =
assertThrows(
HttpResponseException.class,
new ThrowingRunnable() {
@Override
public void run() throws Throwable {
request.execute();
}
});

Assert.assertEquals(500, responseException.getStatusCode());
// original request and 1 retry - total 2
assertEquals(2, responseException.getAttemptCount());
}

public void testUnsupportedCharset() throws Exception {
HttpTransport transport =
new MockHttpTransport() {
Expand Down