options) {
+ Map copyOptions = new HashMap<>();
+ if (options != null) {
+ copyOptions.putAll(options);
+ }
+ copyOptions.put(SpannerRpc.Option.REQUEST_ID, this);
+ return copyOptions;
+ }
+
@Override
public int hashCode() {
return Objects.hash(this.nthClientId, this.nthChannelId, this.nthRequest, this.attempt);
}
+
+ interface RequestIdCreator {
+ XGoogSpannerRequestId nextRequestId(long channelId, int attempt);
+ }
+
+ static class NoopRequestIdCreator implements RequestIdCreator {
+ NoopRequestIdCreator() {}
+
+ @Override
+ public XGoogSpannerRequestId nextRequestId(long channelId, int attempt) {
+ return XGoogSpannerRequestId.of(1, 1, 1, 0);
+ }
+ }
}
diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/admin/instance/v1/package-info.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/admin/instance/v1/package-info.java
index e0c10822cb6..c085e0a6e6c 100644
--- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/admin/instance/v1/package-info.java
+++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/admin/instance/v1/package-info.java
@@ -15,7 +15,7 @@
*/
/**
- * A client to Cloud Spanner Instance Admin API
+ * A client to Cloud Spanner API
*
* The interfaces provided are listed below, along with usage samples.
*
diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/admin/instance/v1/stub/HttpJsonInstanceAdminStub.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/admin/instance/v1/stub/HttpJsonInstanceAdminStub.java
index 55a10bc2436..5af29072b57 100644
--- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/admin/instance/v1/stub/HttpJsonInstanceAdminStub.java
+++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/admin/instance/v1/stub/HttpJsonInstanceAdminStub.java
@@ -1053,6 +1053,26 @@ protected HttpJsonInstanceAdminStub(
HttpRule.newBuilder()
.setPost("/v1/{name=projects/*/instances/*/operations/*}:cancel")
.build())
+ .addAdditionalBindings(
+ HttpRule.newBuilder()
+ .setPost(
+ "/v1/{name=projects/*/instances/*/backups/*/operations/*}:cancel")
+ .build())
+ .addAdditionalBindings(
+ HttpRule.newBuilder()
+ .setPost(
+ "/v1/{name=projects/*/instances/*/instancePartitions/*/operations/*}:cancel")
+ .build())
+ .addAdditionalBindings(
+ HttpRule.newBuilder()
+ .setPost(
+ "/v1/{name=projects/*/instanceConfigs/*/operations/*}:cancel")
+ .build())
+ .addAdditionalBindings(
+ HttpRule.newBuilder()
+ .setPost(
+ "/v1/{name=projects/*/instanceConfigs/*/ssdCaches/*/operations/*}:cancel")
+ .build())
.build())
.put(
"google.longrunning.Operations.DeleteOperation",
@@ -1062,6 +1082,25 @@ protected HttpJsonInstanceAdminStub(
HttpRule.newBuilder()
.setDelete("/v1/{name=projects/*/instances/*/operations/*}")
.build())
+ .addAdditionalBindings(
+ HttpRule.newBuilder()
+ .setDelete(
+ "/v1/{name=projects/*/instances/*/backups/*/operations/*}")
+ .build())
+ .addAdditionalBindings(
+ HttpRule.newBuilder()
+ .setDelete(
+ "/v1/{name=projects/*/instances/*/instancePartitions/*/operations/*}")
+ .build())
+ .addAdditionalBindings(
+ HttpRule.newBuilder()
+ .setDelete("/v1/{name=projects/*/instanceConfigs/*/operations/*}")
+ .build())
+ .addAdditionalBindings(
+ HttpRule.newBuilder()
+ .setDelete(
+ "/v1/{name=projects/*/instanceConfigs/*/ssdCaches/*/operations/*}")
+ .build())
.build())
.put(
"google.longrunning.Operations.GetOperation",
@@ -1071,6 +1110,24 @@ protected HttpJsonInstanceAdminStub(
HttpRule.newBuilder()
.setGet("/v1/{name=projects/*/instances/*/operations/*}")
.build())
+ .addAdditionalBindings(
+ HttpRule.newBuilder()
+ .setGet("/v1/{name=projects/*/instances/*/backups/*/operations/*}")
+ .build())
+ .addAdditionalBindings(
+ HttpRule.newBuilder()
+ .setGet(
+ "/v1/{name=projects/*/instances/*/instancePartitions/*/operations/*}")
+ .build())
+ .addAdditionalBindings(
+ HttpRule.newBuilder()
+ .setGet("/v1/{name=projects/*/instanceConfigs/*/operations/*}")
+ .build())
+ .addAdditionalBindings(
+ HttpRule.newBuilder()
+ .setGet(
+ "/v1/{name=projects/*/instanceConfigs/*/ssdCaches/*/operations/*}")
+ .build())
.build())
.put(
"google.longrunning.Operations.ListOperations",
@@ -1080,6 +1137,24 @@ protected HttpJsonInstanceAdminStub(
HttpRule.newBuilder()
.setGet("/v1/{name=projects/*/instances/*/operations}")
.build())
+ .addAdditionalBindings(
+ HttpRule.newBuilder()
+ .setGet("/v1/{name=projects/*/instances/*/backups/*/operations}")
+ .build())
+ .addAdditionalBindings(
+ HttpRule.newBuilder()
+ .setGet(
+ "/v1/{name=projects/*/instances/*/instancePartitions/*/operations}")
+ .build())
+ .addAdditionalBindings(
+ HttpRule.newBuilder()
+ .setGet("/v1/{name=projects/*/instanceConfigs/*/operations}")
+ .build())
+ .addAdditionalBindings(
+ HttpRule.newBuilder()
+ .setGet(
+ "/v1/{name=projects/*/instanceConfigs/*/ssdCaches/*/operations}")
+ .build())
.build())
.build());
diff --git a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/spi/v1/GapicSpannerRpc.java b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/spi/v1/GapicSpannerRpc.java
index c43bbe1f11b..09aec6f3ebe 100644
--- a/google-cloud-spanner/src/main/java/com/google/cloud/spanner/spi/v1/GapicSpannerRpc.java
+++ b/google-cloud-spanner/src/main/java/com/google/cloud/spanner/spi/v1/GapicSpannerRpc.java
@@ -71,6 +71,7 @@
import com.google.cloud.spanner.SpannerOptions;
import com.google.cloud.spanner.SpannerOptions.CallContextConfigurator;
import com.google.cloud.spanner.SpannerOptions.CallCredentialsProvider;
+import com.google.cloud.spanner.XGoogSpannerRequestId;
import com.google.cloud.spanner.admin.database.v1.stub.DatabaseAdminStub;
import com.google.cloud.spanner.admin.database.v1.stub.DatabaseAdminStubSettings;
import com.google.cloud.spanner.admin.database.v1.stub.GrpcDatabaseAdminCallableFactory;
@@ -85,9 +86,8 @@
import com.google.common.base.Function;
import com.google.common.base.MoreObjects;
import com.google.common.base.Preconditions;
-import com.google.common.base.Supplier;
-import com.google.common.base.Suppliers;
import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.io.Resources;
import com.google.common.util.concurrent.RateLimiter;
@@ -193,6 +193,7 @@
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
+import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
@@ -236,6 +237,7 @@ public class GapicSpannerRpc implements SpannerRpc {
private static final String CLIENT_LIBRARY_LANGUAGE = "spanner-java";
public static final String DEFAULT_USER_AGENT =
CLIENT_LIBRARY_LANGUAGE + "/" + GaxProperties.getLibraryVersion(GapicSpannerRpc.class);
+ public static boolean DIRECTPATH_CHANNEL_CREATED = false;
private static final String API_FILE = "grpc-gcp-apiconfig.json";
private boolean rpcIsClosed;
@@ -278,8 +280,6 @@ public class GapicSpannerRpc implements SpannerRpc {
private final int numChannels;
private final boolean isGrpcGcpExtensionEnabled;
- private Supplier directPathEnabledSupplier = () -> false;
-
private final GrpcCallContext baseGrpcCallContext;
public static GapicSpannerRpc create(SpannerOptions options) {
@@ -358,9 +358,7 @@ public GapicSpannerRpc(final SpannerOptions options) {
SpannerInterceptorProvider.create(
MoreObjects.firstNonNull(
options.getInterceptorProvider(),
- SpannerInterceptorProvider.createDefault(
- options.getOpenTelemetry(),
- (() -> directPathEnabledSupplier.get()))))
+ SpannerInterceptorProvider.createDefault(options.getOpenTelemetry())))
// This sets the trace context headers.
.withTraceContext(endToEndTracingEnabled, options.getOpenTelemetry())
// This sets the response compressor (Server -> Client).
@@ -370,6 +368,10 @@ public GapicSpannerRpc(final SpannerOptions options) {
boolean isAttemptDirectPathXds = isEnableDirectPathXdsEnv();
if (isAttemptDirectPathXds) {
defaultChannelProviderBuilder.setAttemptDirectPath(true);
+ // This will let the credentials try to fetch a hard-bound access token if the runtime
+ // environment supports it.
+ defaultChannelProviderBuilder.setAllowHardBoundTokenTypes(
+ Collections.singletonList(InstantiatingGrpcChannelProvider.HardBoundTokenTypes.ALTS));
defaultChannelProviderBuilder.setAttemptDirectPathXds();
}
@@ -407,6 +409,8 @@ public GapicSpannerRpc(final SpannerOptions options) {
final String emulatorHost = System.getenv("SPANNER_EMULATOR_HOST");
try {
+ // TODO: make our retry settings to inject and increment
+ // XGoogSpannerRequestId whenever a retry occurs.
SpannerStubSettings spannerStubSettings =
options.getSpannerStubSettings().toBuilder()
.setTransportChannelProvider(channelProvider)
@@ -420,12 +424,9 @@ public GapicSpannerRpc(final SpannerOptions options) {
this.spannerStub =
GrpcSpannerStubWithStubSettingsAndClientContext.create(
spannerStubSettings, clientContext);
- this.directPathEnabledSupplier =
- Suppliers.memoize(
- () -> {
- return ((GrpcTransportChannel) clientContext.getTransportChannel()).isDirectPath()
- && isAttemptDirectPathXds;
- });
+ DIRECTPATH_CHANNEL_CREATED =
+ ((GrpcTransportChannel) clientContext.getTransportChannel()).isDirectPath()
+ && isAttemptDirectPathXds;
this.readRetrySettings =
options.getSpannerStubSettings().streamingReadSettings().getRetrySettings();
this.readRetryableCodes =
@@ -677,15 +678,9 @@ private static boolean isEmulatorEnabled(SpannerOptions options, String emulator
}
public static boolean isEnableAFEServerTiming() {
- // Enable AFE metrics and add AFE header if:
- // 1. The env var SPANNER_DISABLE_AFE_SERVER_TIMING is explicitly set to "false", OR
- // 2. DirectPath is enabled AND the env var is not set to "true"
- // This allows metrics to be enabled by default when DirectPath is on, unless explicitly
+ // Enable AFE metrics as default unless explicitly
// disabled via env.
- String afeDisableEnv = System.getenv("SPANNER_DISABLE_AFE_SERVER_TIMING");
- boolean isDirectPathEnabled = isEnableDirectPathXdsEnv();
- return ("false".equalsIgnoreCase(afeDisableEnv))
- || (isDirectPathEnabled && !"true".equalsIgnoreCase(afeDisableEnv));
+ return !Boolean.parseBoolean(System.getenv("SPANNER_DISABLE_AFE_SERVER_TIMING"));
}
public static boolean isEnableDirectPathXdsEnv() {
@@ -1658,7 +1653,7 @@ public Session createSession(
@Nullable Map labels,
@Nullable Map