diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SpannerExceptionFactory.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SpannerExceptionFactory.java index beb9ba2feb38..276e17296ab5 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SpannerExceptionFactory.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SpannerExceptionFactory.java @@ -126,6 +126,8 @@ private static boolean isRetryable(ErrorCode code, @Nullable Throwable cause) { return hasCauseMatching(cause, Matchers.isRetryableInternalError); case UNAVAILABLE: return true; + case RESOURCE_EXHAUSTED: + return true; default: return false; } diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SpannerImpl.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SpannerImpl.java index 885723109ccd..51c9c3869f94 100644 --- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SpannerImpl.java +++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SpannerImpl.java @@ -1284,7 +1284,8 @@ TransactionSelector getTransactionSelector() { @Override public void onError(SpannerException e) { - if (e.getErrorCode() == ErrorCode.ABORTED) { + if (e.getErrorCode() == ErrorCode.ABORTED + || e.getErrorCode() == ErrorCode.RESOURCE_EXHAUSTED) { long delay = -1L; if (e instanceof AbortedException) { delay = ((AbortedException) e).getRetryDelayInMillis(); diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/TransactionRunnerImplTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/TransactionRunnerImplTest.java index 76df1239714b..a70ed68e8439 100644 --- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/TransactionRunnerImplTest.java +++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/TransactionRunnerImplTest.java @@ -78,6 +78,14 @@ public void runAbortNoRetryInfo() { assertThat(backoffMillis.getValue()).isGreaterThan(0L); } + @Test + public void runResourceExhausted() { + runTransaction(new StatusRuntimeException(Status.fromCodeValue(Status.Code.RESOURCE_EXHAUSTED.value()))); + ArgumentCaptor backoffMillis = ArgumentCaptor.forClass(Long.class); + verify(sleeper, times(1)).backoffSleep(Mockito.any(), backoffMillis.capture()); + assertThat(backoffMillis.getValue()).isGreaterThan(0L); + } + @Test public void commitAbort() { final SpannerException error =