Skip to content

Commit 6ed90f8

Browse files
fix retry in GCS storage client
1 parent 7d57b20 commit 6ed90f8

4 files changed

Lines changed: 8 additions & 148 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
# Changelog
44
- v4.3.2-SNAPSHOT
5+
- Fixed GCS PUT operations not retrying on transient errors (e.g. HTTP 503) despite `putgetmaxretries` being configured (snowflakedb/snowflake-jdbc#2688).
56
- Bumped jackson-databind to 2.18.8 from 2.18.7 (snowflakedb/snowflake-jdbc#2669).
67
- Fixed snowflake-jdbc writing a `snowflake-minicore-*` temp directory and loading the native library at driver class-load time even when the driver was never used (e.g. when present on the classpath only as a transitive dependency). Minicore now loads lazily when the first Snowflake connection is created (`ConnectionFactory.createConnection`) instead of during `DriverInitializer.initialize()` (snowflakedb/snowflake-jdbc#2670).
78
- Restored `GetCallerIdentity` as the default AWS Workload Identity Federation attestation method to avoid breaking existing users who have not configured the `ISSUER` in their Snowflake WIF setup. The `GetWebIdentityToken` (outbound JWT) flow introduced in v4.3.0 is now opt-in via the new `workloadIdentityAwsUseOutboundToken` connection property.

src/main/java/net/snowflake/client/internal/jdbc/cloud/storage/GCSAccessStrategyAwsSdk.java

Lines changed: 5 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -261,46 +261,20 @@ public boolean handleStorageException(
261261
String queryId,
262262
SnowflakeGCSClient gcsClient)
263263
throws SnowflakeSQLException {
264-
// Find an SdkException either directly in the cause or anywhere in the cause chain.
265-
// When the exception originates from the inner uploadWithDownScopedToken it arrives wrapped
266-
// in SnowflakeSQLLoggedException(CompletionException(SdkException)); walking the chain
267-
// ensures transient errors are always treated as retryable regardless of wrapping depth.
268-
SdkException sdkEx = null;
269264
Throwable cause = ex.getCause();
270-
while (cause != null) {
271-
if (cause instanceof SdkException) {
272-
sdkEx = (SdkException) cause;
273-
break;
274-
}
275-
cause = cause.getCause();
276-
}
277-
278-
if (sdkEx != null) {
279-
if (sdkEx != ex.getCause()) {
280-
logger.debug(
281-
"GCSAccessStrategyAwsSdk: found SdkException wrapped inside {} during {};"
282-
+ " treating as retryable",
283-
ex.getClass().getSimpleName(),
284-
operation);
285-
}
286-
logger.debug("GCSAccessStrategyAwsSdk: " + sdkEx.getMessage());
265+
if (cause instanceof SdkException) {
266+
logger.debug("GCSAccessStrategyAwsSdk: " + cause.getMessage());
287267

288268
if (retryCount > gcsClient.getMaxRetries()
289-
|| S3ErrorHandler.isClientException400Or404(sdkEx)) {
269+
|| S3ErrorHandler.isClientException400Or404(cause)) {
290270
throwIfClientExceptionOrMaxRetryReached(
291-
operation, session, command, queryId, gcsClient, sdkEx);
271+
operation, session, command, queryId, gcsClient, cause);
292272
} else {
293273
retryRequestWithExponentialBackoff(
294-
ex, retryCount, operation, session, command, gcsClient, queryId, sdkEx);
274+
ex, retryCount, operation, session, command, gcsClient, queryId, cause);
295275
}
296276
return true;
297277
} else {
298-
logger.error(
299-
"GCSAccessStrategyAwsSdk: unhandled exception type {} during {}, not retrying: {}",
300-
ex.getClass().getName(),
301-
operation,
302-
ex.getMessage());
303-
logger.error("Stack trace: ", ex);
304278
return false;
305279
}
306280
}

src/main/java/net/snowflake/client/internal/jdbc/cloud/storage/GCSDefaultAccessStrategy.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,8 @@ public boolean handleStorageException(
207207
// The exception may arrive wrapped (e.g. in SnowflakeSQLException) when it originates from the
208208
// inner uploadWithDownScopedToken method, which catches the original StorageException and
209209
// re-wraps it before re-throwing. Walking the chain ensures that a transient 503 or similar
210-
// GCS error is always treated as retryable regardless of how many layers of wrapping were added.
210+
// GCS error is always treated as retryable regardless of how many layers of wrapping were
211+
// added.
211212
StorageException se = null;
212213
if (ex instanceof StorageException) {
213214
se = (StorageException) ex;

src/test/java/net/snowflake/client/internal/jdbc/cloud/storage/GCSAccessStrategyAwsSdkTest.java

Lines changed: 0 additions & 116 deletions
This file was deleted.

0 commit comments

Comments
 (0)