diff --git a/README.md b/README.md
index e38127306f9..7042c600b79 100644
--- a/README.md
+++ b/README.md
@@ -57,13 +57,13 @@ implementation 'com.google.cloud:google-cloud-spanner'
If you are using Gradle without BOM, add this to your dependencies:
```Groovy
-implementation 'com.google.cloud:google-cloud-spanner:6.42.2'
+implementation 'com.google.cloud:google-cloud-spanner:6.42.3'
```
If you are using SBT, add this to your dependencies:
```Scala
-libraryDependencies += "com.google.cloud" % "google-cloud-spanner" % "6.42.2"
+libraryDependencies += "com.google.cloud" % "google-cloud-spanner" % "6.42.3"
```
@@ -412,7 +412,7 @@ Java is a registered trademark of Oracle and/or its affiliates.
[kokoro-badge-link-5]: http://storage.googleapis.com/cloud-devrel-public/java/badges/java-spanner/java11.html
[stability-image]: https://img.shields.io/badge/stability-stable-green
[maven-version-image]: https://img.shields.io/maven-central/v/com.google.cloud/google-cloud-spanner.svg
-[maven-version-link]: https://central.sonatype.com/artifact/com.google.cloud/google-cloud-spanner/6.42.2
+[maven-version-link]: https://central.sonatype.com/artifact/com.google.cloud/google-cloud-spanner/6.42.3
[authentication]: https://github.com/googleapis/google-cloud-java#authentication
[auth-scopes]: https://developers.google.com/identity/protocols/oauth2/scopes
[predefined-iam-roles]: https://cloud.google.com/iam/docs/understanding-roles#predefined_roles
diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SpannerOptions.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SpannerOptions.java
index 6663d3f8e68..33fa826bfec 100644
--- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SpannerOptions.java
+++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/SpannerOptions.java
@@ -993,13 +993,26 @@ public Builder setAutoThrottleAdministrativeRequests() {
return this;
}
+ /**
+ * Disables automatic retries of administrative requests that fail if the https://cloud.google.com/spanner/quotas#administrative_limits
+ * have been exceeded. You should disable these retries if you intend to handle these errors in
+ * your application.
+ */
+ public Builder disableAdministrativeRequestRetries() {
+ this.retryAdministrativeRequestsSettings =
+ this.retryAdministrativeRequestsSettings.toBuilder().setMaxAttempts(1).build();
+ return this;
+ }
+
/**
* Sets the retry settings for retrying administrative requests when the quote of administrative
* requests per minute has been exceeded.
*/
Builder setRetryAdministrativeRequestsSettings(
RetrySettings retryAdministrativeRequestsSettings) {
- this.retryAdministrativeRequestsSettings = retryAdministrativeRequestsSettings;
+ this.retryAdministrativeRequestsSettings =
+ Preconditions.checkNotNull(retryAdministrativeRequestsSettings);
return this;
}
diff --git a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/DatabaseAdminClientTest.java b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/DatabaseAdminClientTest.java
index eee9f520a7d..5ef7b508049 100644
--- a/google-cloud-spanner/src/test/java/com/google/cloud/spanner/DatabaseAdminClientTest.java
+++ b/google-cloud-spanner/src/test/java/com/google/cloud/spanner/DatabaseAdminClientTest.java
@@ -935,4 +935,31 @@ public void testRetryOperationOnAdminMethodQuotaPerMinutePerProjectExceeded() {
assertEquals(DB_ID, database.getId().getDatabase());
assertEquals(2, mockDatabaseAdmin.countRequestsOfType(GetDatabaseRequest.class));
}
+
+ @Test
+ public void testRetriesDisabledForOperationOnAdminMethodQuotaPerMinutePerProjectExceeded() {
+ ErrorInfo info =
+ ErrorInfo.newBuilder()
+ .putMetadata("quota_limit", "AdminMethodQuotaPerMinutePerProject")
+ .build();
+ Metadata.Key key =
+ Metadata.Key.of(
+ info.getDescriptorForType().getFullName() + Metadata.BINARY_HEADER_SUFFIX,
+ ProtoLiteUtils.metadataMarshaller(info));
+ Metadata trailers = new Metadata();
+ trailers.put(key, info);
+ mockDatabaseAdmin.addException(
+ Status.RESOURCE_EXHAUSTED.withDescription("foo").asRuntimeException(trailers));
+ mockDatabaseAdmin.clearRequests();
+
+ Spanner spannerWithoutRetries =
+ spanner.getOptions().toBuilder().disableAdministrativeRequestRetries().build().getService();
+ AdminRequestsPerMinuteExceededException exception =
+ assertThrows(
+ AdminRequestsPerMinuteExceededException.class,
+ () -> spannerWithoutRetries.getDatabaseAdminClient().getDatabase(INSTANCE_ID, DB_ID));
+ assertEquals(ErrorCode.RESOURCE_EXHAUSTED, exception.getErrorCode());
+ // There should be only one request on the server, as the request was not retried.
+ assertEquals(1, mockDatabaseAdmin.countRequestsOfType(GetDatabaseRequest.class));
+ }
}