Skip to content
This repository was archived by the owner on Apr 7, 2026. It is now read-only.

Commit a9bb6dd

Browse files
authored
Merge branch 'main' into x-goog-spanner-request-id-smaller-PR-updates-from-prior-review
2 parents 6261a92 + d754f1f commit a9bb6dd

13 files changed

Lines changed: 95 additions & 22 deletions

File tree

google-cloud-spanner/clirr-ignored-differences.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1028,4 +1028,9 @@
10281028
<className>com/google/cloud/spanner/StructReader</className>
10291029
<method>java.lang.Object getOrDefault(java.lang.String, java.util.function.BiFunction, java.lang.Object)</method>
10301030
</difference>
1031+
<difference>
1032+
<differenceType>7012</differenceType>
1033+
<className>com/google/cloud/spanner/SpannerOptions$SpannerEnvironment</className>
1034+
<method>boolean isEnableDirectAccess()</method>
1035+
</difference>
10311036
</differences>

google-cloud-spanner/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -592,7 +592,7 @@
592592
<spanner.testenv.config.class>com.google.cloud.spanner.GceTestEnvConfig</spanner.testenv.config.class>
593593
<spanner.testenv.instance>projects/directpath-prod-manual-testing/instances/spanner-testing</spanner.testenv.instance>
594594
<spanner.gce.config.project_id>directpath-prod-manual-testing</spanner.gce.config.project_id>
595-
<spanner.attempt_directpath>true</spanner.attempt_directpath>
595+
<spanner.enable_direct_access>true</spanner.enable_direct_access>
596596
<spanner.directpath_test_scenario>ipv4</spanner.directpath_test_scenario>
597597
</systemPropertyVariables>
598598
<forkedProcessTimeoutInSeconds>3000</forkedProcessTimeoutInSeconds>

google-cloud-spanner/src/main/java/com/google/cloud/spanner/SpannerOptions.java

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ public class SpannerOptions extends ServiceOptions<Spanner, SpannerOptions> {
175175
private final CloseableExecutorProvider asyncExecutorProvider;
176176
private final String compressorName;
177177
private final boolean leaderAwareRoutingEnabled;
178-
private final boolean attemptDirectPath;
178+
private final boolean enableDirectAccess;
179179
private final DirectedReadOptions directedReadOptions;
180180
private final boolean useVirtualThreads;
181181
private final OpenTelemetry openTelemetry;
@@ -806,7 +806,7 @@ protected SpannerOptions(Builder builder) {
806806
asyncExecutorProvider = builder.asyncExecutorProvider;
807807
compressorName = builder.compressorName;
808808
leaderAwareRoutingEnabled = builder.leaderAwareRoutingEnabled;
809-
attemptDirectPath = builder.attemptDirectPath;
809+
enableDirectAccess = builder.enableDirectAccess;
810810
directedReadOptions = builder.directedReadOptions;
811811
useVirtualThreads = builder.useVirtualThreads;
812812
openTelemetry = builder.openTelemetry;
@@ -849,6 +849,10 @@ default boolean isEnableApiTracing() {
849849
return false;
850850
}
851851

852+
default boolean isEnableDirectAccess() {
853+
return false;
854+
}
855+
852856
default boolean isEnableBuiltInMetrics() {
853857
return true;
854858
}
@@ -884,6 +888,8 @@ private static class SpannerEnvironmentImpl implements SpannerEnvironment {
884888
"SPANNER_OPTIMIZER_STATISTICS_PACKAGE";
885889
private static final String SPANNER_ENABLE_EXTENDED_TRACING = "SPANNER_ENABLE_EXTENDED_TRACING";
886890
private static final String SPANNER_ENABLE_API_TRACING = "SPANNER_ENABLE_API_TRACING";
891+
private static final String GOOGLE_SPANNER_ENABLE_DIRECT_ACCESS =
892+
"GOOGLE_SPANNER_ENABLE_DIRECT_ACCESS";
887893
private static final String SPANNER_ENABLE_END_TO_END_TRACING =
888894
"SPANNER_ENABLE_END_TO_END_TRACING";
889895
private static final String SPANNER_DISABLE_BUILTIN_METRICS = "SPANNER_DISABLE_BUILTIN_METRICS";
@@ -916,6 +922,11 @@ public boolean isEnableApiTracing() {
916922
return Boolean.parseBoolean(System.getenv(SPANNER_ENABLE_API_TRACING));
917923
}
918924

925+
@Override
926+
public boolean isEnableDirectAccess() {
927+
return Boolean.parseBoolean(System.getenv(GOOGLE_SPANNER_ENABLE_DIRECT_ACCESS));
928+
}
929+
919930
@Override
920931
public boolean isEnableBuiltInMetrics() {
921932
return !Boolean.parseBoolean(System.getenv(SPANNER_DISABLE_BUILTIN_METRICS));
@@ -1000,7 +1011,7 @@ public static class Builder
10001011
private String compressorName;
10011012
private String emulatorHost = System.getenv("SPANNER_EMULATOR_HOST");
10021013
private boolean leaderAwareRoutingEnabled = true;
1003-
private boolean attemptDirectPath = true;
1014+
private boolean enableDirectAccess = SpannerOptions.environment.isEnableDirectAccess();
10041015
private DirectedReadOptions directedReadOptions;
10051016
private boolean useVirtualThreads = false;
10061017
private OpenTelemetry openTelemetry;
@@ -1072,7 +1083,7 @@ protected Builder() {
10721083
this.channelProvider = options.channelProvider;
10731084
this.channelConfigurator = options.channelConfigurator;
10741085
this.interceptorProvider = options.interceptorProvider;
1075-
this.attemptDirectPath = options.attemptDirectPath;
1086+
this.enableDirectAccess = options.enableDirectAccess;
10761087
this.directedReadOptions = options.directedReadOptions;
10771088
this.useVirtualThreads = options.useVirtualThreads;
10781089
this.enableApiTracing = options.enableApiTracing;
@@ -1605,8 +1616,15 @@ public Builder disableLeaderAwareRouting() {
16051616
}
16061617

16071618
@BetaApi
1619+
public Builder setEnableDirectAccess(boolean enableDirectAccess) {
1620+
this.enableDirectAccess = enableDirectAccess;
1621+
return this;
1622+
}
1623+
1624+
@ObsoleteApi("Use setEnableDirectAccess(false) instead")
1625+
@Deprecated
16081626
public Builder disableDirectPath() {
1609-
this.attemptDirectPath = false;
1627+
this.enableDirectAccess = false;
16101628
return this;
16111629
}
16121630

@@ -1974,8 +1992,14 @@ public DirectedReadOptions getDirectedReadOptions() {
19741992
}
19751993

19761994
@BetaApi
1995+
public Boolean isEnableDirectAccess() {
1996+
return enableDirectAccess;
1997+
}
1998+
1999+
@ObsoleteApi("Use isEnableDirectAccess() instead")
2000+
@Deprecated
19772001
public boolean isAttemptDirectPath() {
1978-
return attemptDirectPath;
2002+
return enableDirectAccess;
19792003
}
19802004

19812005
/**

google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ConnectionOptions.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import static com.google.cloud.spanner.connection.ConnectionProperties.DATA_BOOST_ENABLED;
2929
import static com.google.cloud.spanner.connection.ConnectionProperties.DIALECT;
3030
import static com.google.cloud.spanner.connection.ConnectionProperties.ENABLE_API_TRACING;
31+
import static com.google.cloud.spanner.connection.ConnectionProperties.ENABLE_DIRECT_ACCESS;
3132
import static com.google.cloud.spanner.connection.ConnectionProperties.ENABLE_END_TO_END_TRACING;
3233
import static com.google.cloud.spanner.connection.ConnectionProperties.ENABLE_EXTENDED_TRACING;
3334
import static com.google.cloud.spanner.connection.ConnectionProperties.ENCODED_CREDENTIALS;
@@ -1081,6 +1082,10 @@ boolean isExperimentalHost() {
10811082
return getInitialConnectionPropertyValue(IS_EXPERIMENTAL_HOST);
10821083
}
10831084

1085+
Boolean isEnableDirectAccess() {
1086+
return getInitialConnectionPropertyValue(ENABLE_DIRECT_ACCESS);
1087+
}
1088+
10841089
String getClientCertificate() {
10851090
return getInitialConnectionPropertyValue(CLIENT_CERTIFICATE);
10861091
}

google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/ConnectionProperties.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,20 @@ public class ConnectionProperties {
183183
BOOLEANS,
184184
BooleanConverter.INSTANCE,
185185
Context.STARTUP);
186+
static final ConnectionProperty<Boolean> ENABLE_DIRECT_ACCESS =
187+
create(
188+
"enableDirectAccess",
189+
"Configure the connection to try to connect to Spanner using "
190+
+ "DirectPath (true/false). The client will try to connect to Spanner "
191+
+ "using a direct Google network connection. DirectPath will work only "
192+
+ "if the client is trying to establish a connection from a Google Cloud VM. "
193+
+ "Otherwise it will automatically fallback to the standard network path. "
194+
+ "NOTE: The default for this property is currently false, "
195+
+ "but this could be changed in the future.",
196+
null,
197+
BOOLEANS,
198+
BooleanConverter.INSTANCE,
199+
Context.STARTUP);
186200
static final ConnectionProperty<Boolean> USE_AUTO_SAVEPOINTS_FOR_EMULATOR =
187201
create(
188202
"useAutoSavepointsForEmulator",

google-cloud-spanner/src/main/java/com/google/cloud/spanner/connection/SpannerPool.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,7 @@ static class SpannerPoolKey {
164164
private final String clientCertificate;
165165
private final String clientCertificateKey;
166166
private final boolean isExperimentalHost;
167+
private final Boolean enableDirectAccess;
167168

168169
@VisibleForTesting
169170
static SpannerPoolKey of(ConnectionOptions options) {
@@ -198,6 +199,7 @@ private SpannerPoolKey(ConnectionOptions options) throws IOException {
198199
this.clientCertificate = options.getClientCertificate();
199200
this.clientCertificateKey = options.getClientCertificateKey();
200201
this.isExperimentalHost = options.isExperimentalHost();
202+
this.enableDirectAccess = options.isEnableDirectAccess();
201203
}
202204

203205
@Override
@@ -223,7 +225,8 @@ public boolean equals(Object o) {
223225
&& Objects.equals(this.enableEndToEndTracing, other.enableEndToEndTracing)
224226
&& Objects.equals(this.clientCertificate, other.clientCertificate)
225227
&& Objects.equals(this.clientCertificateKey, other.clientCertificateKey)
226-
&& Objects.equals(this.isExperimentalHost, other.isExperimentalHost);
228+
&& Objects.equals(this.isExperimentalHost, other.isExperimentalHost)
229+
&& Objects.equals(this.enableDirectAccess, other.enableDirectAccess);
227230
}
228231

229232
@Override
@@ -245,7 +248,8 @@ public int hashCode() {
245248
this.enableEndToEndTracing,
246249
this.clientCertificate,
247250
this.clientCertificateKey,
248-
this.isExperimentalHost);
251+
this.isExperimentalHost,
252+
this.enableDirectAccess);
249253
}
250254
}
251255

@@ -412,6 +416,9 @@ Spanner createSpanner(SpannerPoolKey key, ConnectionOptions options) {
412416
if (key.isExperimentalHost) {
413417
builder.setExperimentalHost(key.host);
414418
}
419+
if (key.enableDirectAccess != null) {
420+
builder.setEnableDirectAccess(key.enableDirectAccess);
421+
}
415422
if (options.getConfigurator() != null) {
416423
options.getConfigurator().configure(builder);
417424
}

google-cloud-spanner/src/main/java/com/google/cloud/spanner/spi/v1/GapicSpannerRpc.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -365,8 +365,8 @@ public GapicSpannerRpc(final SpannerOptions options) {
365365
.withEncoding(compressorName))
366366
.setHeaderProvider(headerProviderWithUserAgent)
367367
.setAllowNonDefaultServiceAccount(true);
368-
boolean isAttemptDirectPathXds = isEnableDirectPathXdsEnv();
369-
if (isAttemptDirectPathXds) {
368+
boolean isEnableDirectAccess = options.isEnableDirectAccess();
369+
if (isEnableDirectAccess) {
370370
defaultChannelProviderBuilder.setAttemptDirectPath(true);
371371
// This will let the credentials try to fetch a hard-bound access token if the runtime
372372
// environment supports it.
@@ -426,7 +426,7 @@ public GapicSpannerRpc(final SpannerOptions options) {
426426
spannerStubSettings, clientContext);
427427
DIRECTPATH_CHANNEL_CREATED =
428428
((GrpcTransportChannel) clientContext.getTransportChannel()).isDirectPath()
429-
&& isAttemptDirectPathXds;
429+
&& isEnableDirectAccess;
430430
this.readRetrySettings =
431431
options.getSpannerStubSettings().streamingReadSettings().getRetrySettings();
432432
this.readRetryableCodes =

google-cloud-spanner/src/test/java/com/google/cloud/spanner/GceTestEnvConfig.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ public class GceTestEnvConfig implements TestEnvConfig {
4646
public static final String GCE_CREDENTIALS_FILE = "spanner.gce.config.credentials_file";
4747
public static final String GCE_STREAM_BROKEN_PROBABILITY =
4848
"spanner.gce.config.stream_broken_probability";
49-
public static final String ATTEMPT_DIRECT_PATH = "spanner.attempt_directpath";
49+
public static final String ENABLE_DIRECT_ACCESS = "spanner.enable_direct_access";
5050
public static final String DIRECT_PATH_TEST_SCENARIO = "spanner.directpath_test_scenario";
5151

5252
// IP address prefixes allocated for DirectPath backends.
@@ -64,7 +64,7 @@ public GceTestEnvConfig() {
6464
double errorProbability =
6565
Double.parseDouble(System.getProperty(GCE_STREAM_BROKEN_PROBABILITY, "0.0"));
6666
checkState(errorProbability <= 1.0);
67-
boolean attemptDirectPath = Boolean.getBoolean(ATTEMPT_DIRECT_PATH);
67+
boolean enableDirectAccess = Boolean.getBoolean(ENABLE_DIRECT_ACCESS);
6868
String directPathTestScenario = System.getProperty(DIRECT_PATH_TEST_SCENARIO, "");
6969
SpannerOptions.Builder builder =
7070
SpannerOptions.newBuilder()
@@ -85,15 +85,15 @@ public GceTestEnvConfig() {
8585
}
8686
SpannerInterceptorProvider interceptorProvider =
8787
SpannerInterceptorProvider.createDefault().with(new GrpcErrorInjector(errorProbability));
88-
if (attemptDirectPath) {
88+
if (enableDirectAccess) {
8989
interceptorProvider =
9090
interceptorProvider.with(new DirectPathAddressCheckInterceptor(directPathTestScenario));
9191
}
9292
builder.setInterceptorProvider(interceptorProvider);
9393
// DirectPath tests need to set a custom endpoint to the ChannelProvider
9494
InstantiatingGrpcChannelProvider.Builder customChannelProviderBuilder =
9595
InstantiatingGrpcChannelProvider.newBuilder();
96-
if (attemptDirectPath) {
96+
if (enableDirectAccess) {
9797
customChannelProviderBuilder
9898
.setEndpoint(DIRECT_PATH_ENDPOINT)
9999
.setAttemptDirectPath(true)

google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/ConnectionOptionsTest.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1311,4 +1311,22 @@ public void testExperimentalHost() {
13111311
.getSessionPoolOptions()
13121312
.getUseMultiplexedSessionPartitionedOps());
13131313
}
1314+
1315+
@Test
1316+
public void testEnableDirectAccess() {
1317+
ConnectionOptions.Builder builderWithoutDirectPathParam = ConnectionOptions.newBuilder();
1318+
builderWithoutDirectPathParam.setUri(
1319+
"spanner://localhost:15000/instances/default/databases/singers-db;usePlainText=true");
1320+
assertNull(builderWithoutDirectPathParam.build().isEnableDirectAccess());
1321+
1322+
ConnectionOptions.Builder builderWithDirectPathParamFalse = ConnectionOptions.newBuilder();
1323+
builderWithDirectPathParamFalse.setUri(
1324+
"spanner://localhost:15000/instances/default/databases/singers-db;usePlainText=true;enableDirectAccess=false");
1325+
assertFalse(builderWithDirectPathParamFalse.build().isEnableDirectAccess());
1326+
1327+
ConnectionOptions.Builder builderWithDirectPathParam = ConnectionOptions.newBuilder();
1328+
builderWithDirectPathParam.setUri(
1329+
"spanner://localhost:15000/projects/default/instances/default/databases/singers-db;usePlainText=true;enableDirectAccess=true");
1330+
assertTrue(builderWithDirectPathParam.build().isEnableDirectAccess());
1331+
}
13141332
}

google-cloud-spanner/src/test/java/com/google/cloud/spanner/connection/CredentialsProviderTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ public void testCredentialsProvider() throws Throwable {
9393
.setConfigurator(
9494
spannerOptions -> {
9595
spannerOptions.setChannelConfigurator(ManagedChannelBuilder::usePlaintext);
96-
spannerOptions.disableDirectPath();
96+
spannerOptions.setEnableDirectAccess(false);
9797
})
9898
.build();
9999

@@ -135,7 +135,7 @@ public void testCredentialsProvider() throws Throwable {
135135
.setConfigurator(
136136
spannerOptions -> {
137137
spannerOptions.setChannelConfigurator(ManagedChannelBuilder::usePlaintext);
138-
spannerOptions.disableDirectPath();
138+
spannerOptions.setEnableDirectAccess(false);
139139
})
140140
.build();
141141
try (Connection connection = options.getConnection()) {

0 commit comments

Comments
 (0)