Repository navigation
feat(gax): standardize mapping terminal resumable upload exceptions to ApiException #14624
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
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -212,14 +212,15 @@ | |
| } | ||
|
|
||
| private void onTimeout() { | ||
| String sessionUrl = uploadSessionUrl; | ||
| String message; | ||
| if (sessionUrl != null) { | ||
| message = "Resumable upload timed out for session: " + sessionUrl; | ||
| if (uploadSessionUrl != null) { | ||
| message = "Resumable upload timed out"; | ||
| } else { | ||
| message = "Resumable upload timed out before session initiation completed"; | ||
| } | ||
| fail(ApiExceptionFactory.createException(message, null, TIMEOUT_STATUS_CODE, false)); | ||
| fail( | ||
| ApiExceptionFactory.createException( | ||
| message, null, statusCodeOf(StatusCode.Code.DEADLINE_EXCEEDED), false)); | ||
| } | ||
|
|
||
| private void succeed(@Nullable ResponseT result) { | ||
|
|
@@ -229,7 +230,7 @@ | |
| } | ||
| inFlightFuture = null; | ||
| } | ||
| closePayload(); | ||
| closePayload(null); | ||
| resultFuture.set(result); | ||
| } | ||
|
|
||
|
|
@@ -243,19 +244,44 @@ | |
| inFlightFuture = null; | ||
| } | ||
| inFlight.cancel(true); | ||
| ApiException terminal = toTerminalException(t); | ||
| progressTracker.onFailed(); | ||
| closePayload(); | ||
| resultFuture.setException(t); | ||
| closePayload(terminal); | ||
| resultFuture.setException(terminal); | ||
| } | ||
|
|
||
| private void closePayload() { | ||
| private ApiException toTerminalException(Throwable t) { | ||
| if (t instanceof ApiException && uploadSessionUrl == null) { | ||
| return (ApiException) t; | ||
| } | ||
| String message = firstNonNull(t.getMessage(), t.getClass().getSimpleName()); | ||
| if (uploadSessionUrl != null) { | ||
| message = message + " (upload URL: " + uploadSessionUrl + ")"; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We might missed this in previous PRs. I think the upload URL contains an upload id, and anyone with the id can upload without authentication? If that's the case, I think it would be better to not include the full url in the log.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This did come up in an earlier PR - revisiting this I think that we're required to surface the full URL. From internal cross-language design docs: "The Client Libraries should include the upload URL as part of the errors it returns to the end-user when resumable upload-related errors occur." and "The upload URL can be configured (in the server configuration) to be completely arbitrary, so we cannot guarantee that we can parse the upload ID. The URL will have to be surfaced in its entirety." |
||
| } | ||
| // Rethrow with URL included in message. | ||
| if (t instanceof ApiException) { | ||
| ApiException apiException = (ApiException) t; | ||
| return ApiExceptionFactory.createException( | ||
| message, | ||
| apiException.getCause(), | ||
| apiException.getStatusCode(), | ||
| apiException.isRetryable(), | ||
| apiException.getErrorDetails()); | ||
| } | ||
| return ApiExceptionFactory.createException( | ||
| message, t, statusCodeOf(StatusCode.Code.UNKNOWN), false); | ||
| } | ||
|
|
||
| private void closePayload(@Nullable Throwable primaryException) { | ||
| if (payload == null) { | ||
| return; | ||
| } | ||
| try { | ||
| payload.close(); | ||
| } catch (IOException ignored) { | ||
| // Suppressed during stream cleanup | ||
| } catch (Throwable e) { | ||
|
Check warning on line 281 in sdk-platform-java/gax-java/gax/src/main/java/com/google/api/gax/rpc/ResumableUploadFutureImpl.java
|
||
| if (primaryException != null) { | ||
| primaryException.addSuppressed(e); | ||
| } | ||
| } | ||
| } | ||
|
whowes marked this conversation as resolved.
|
||
|
|
||
|
|
@@ -283,7 +309,7 @@ | |
| } | ||
| inFlight.cancel(mayInterruptIfRunning); | ||
| progressTracker.onFailed(); | ||
| closePayload(); | ||
| closePayload(null); | ||
| return cancelled; | ||
| } | ||
|
|
||
|
|
@@ -308,16 +334,17 @@ | |
| return resultFuture.get(timeout, unit); | ||
| } | ||
|
|
||
| private static final StatusCode TIMEOUT_STATUS_CODE = | ||
| new StatusCode() { | ||
| @Override | ||
| public StatusCode.Code getCode() { | ||
| return StatusCode.Code.DEADLINE_EXCEEDED; | ||
| } | ||
| private static StatusCode statusCodeOf(StatusCode.Code code) { | ||
| return new StatusCode() { | ||
| @Override | ||
| public StatusCode.Code getCode() { | ||
| return code; | ||
| } | ||
|
|
||
| @Override | ||
| public @Nullable Object getTransportCode() { | ||
| return null; | ||
| } | ||
| }; | ||
| @Override | ||
| public @Nullable Object getTransportCode() { | ||
| return null; | ||
| } | ||
| }; | ||
| } | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.