Skip to content

Commit e12cd0f

Browse files
committed
Merge branch 'main' of https://github.com/googleapis/java-spanner into grpc-telemetry-client-interceptor
2 parents b62b3c0 + 95da1ed commit e12cd0f

37 files changed

+1086
-45
lines changed

.github/workflows/unmanaged_dependency_check.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,6 @@ jobs:
1717
# repository
1818
.kokoro/build.sh
1919
- name: Unmanaged dependency check
20-
uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.33.0
20+
uses: googleapis/sdk-platform-java/java-shared-dependencies/unmanaged-dependency-check@google-cloud-shared-dependencies/v3.34.0
2121
with:
2222
bom-path: google-cloud-spanner-bom/pom.xml

.kokoro/presubmit/graalvm-native-17.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
# Configure the docker image for kokoro-trampoline.
44
env_vars: {
55
key: "TRAMPOLINE_IMAGE"
6-
value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.33.0"
6+
value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_b:3.34.0"
77
}
88

99
env_vars: {

.kokoro/presubmit/graalvm-native.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
# Configure the docker image for kokoro-trampoline.
44
env_vars: {
55
key: "TRAMPOLINE_IMAGE"
6-
value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.33.0"
6+
value: "gcr.io/cloud-devrel-public-resources/graalvm_sdk_platform_a:3.34.0"
77
}
88

99
env_vars: {

benchmarks/pom.xml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
3535
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
3636
<junixsocket.version>2.10.0</junixsocket.version>
37-
<opentelemetry.version>1.40.0</opentelemetry.version>
37+
<opentelemetry.version>1.41.0</opentelemetry.version>
3838
</properties>
3939

4040
<dependencies>
@@ -85,19 +85,19 @@
8585
<dependency>
8686
<groupId>io.opentelemetry</groupId>
8787
<artifactId>opentelemetry-bom</artifactId>
88-
<version>1.40.0</version>
88+
<version>1.41.0</version>
8989
<type>pom</type>
9090
<scope>import</scope>
9191
</dependency>
9292
<dependency>
9393
<groupId>com.google.cloud</groupId>
9494
<artifactId>google-cloud-spanner</artifactId>
95-
<version>6.71.0</version>
95+
<version>6.72.0</version>
9696
</dependency>
9797
<dependency>
9898
<groupId>commons-cli</groupId>
9999
<artifactId>commons-cli</artifactId>
100-
<version>1.8.0</version>
100+
<version>1.9.0</version>
101101
</dependency>
102102
<dependency>
103103
<groupId>com.google.auto.value</groupId>
@@ -118,7 +118,7 @@
118118
<dependency>
119119
<groupId>commons-cli</groupId>
120120
<artifactId>commons-cli</artifactId>
121-
<version>1.8.0</version>
121+
<version>1.9.0</version>
122122
</dependency>
123123

124124
<dependency>
@@ -133,7 +133,7 @@
133133
<plugin>
134134
<groupId>org.codehaus.mojo</groupId>
135135
<artifactId>exec-maven-plugin</artifactId>
136-
<version>3.4.0</version>
136+
<version>3.4.1</version>
137137
<configuration>
138138
<mainClass>com.google.cloud.spanner.benchmark.LatencyBenchmark</mainClass>
139139
<cleanupDaemonThreads>false</cleanupDaemonThreads>

google-cloud-spanner-bom/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
<parent>
99
<groupId>com.google.cloud</groupId>
1010
<artifactId>sdk-platform-java-config</artifactId>
11-
<version>3.33.0</version>
11+
<version>3.34.0</version>
1212
</parent>
1313

1414
<name>Google Cloud Spanner BOM</name>

google-cloud-spanner-executor/pom.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@
129129
<dependency>
130130
<groupId>commons-cli</groupId>
131131
<artifactId>commons-cli</artifactId>
132-
<version>1.8.0</version>
132+
<version>1.9.0</version>
133133
</dependency>
134134
<dependency>
135135
<groupId>commons-io</groupId>
@@ -188,7 +188,7 @@
188188
<plugin>
189189
<groupId>org.apache.maven.plugins</groupId>
190190
<artifactId>maven-failsafe-plugin</artifactId>
191-
<version>3.3.1</version>
191+
<version>3.4.0</version>
192192
</plugin>
193193
</plugins>
194194
<pluginManagement>

google-cloud-spanner/pom.xml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,12 @@
359359
<version>${graal-sdk.version}</version>
360360
<scope>provided</scope>
361361
</dependency>
362+
<dependency>
363+
<groupId>org.graalvm.sdk</groupId>
364+
<artifactId>nativeimage</artifactId>
365+
<version>${graal-sdk.version}</version>
366+
<scope>provided</scope>
367+
</dependency>
362368

363369
<!-- Test dependencies -->
364370
<dependency>
@@ -411,7 +417,7 @@
411417
<dependency>
412418
<groupId>org.hamcrest</groupId>
413419
<artifactId>hamcrest</artifactId>
414-
<version>2.2</version>
420+
<version>3.0</version>
415421
<scope>test</scope>
416422
</dependency>
417423
<!-- Benchmarking dependencies -->

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

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import com.google.cloud.spanner.SessionClient.SessionOption;
3737
import com.google.cloud.spanner.SessionImpl.SessionTransaction;
3838
import com.google.cloud.spanner.spi.v1.SpannerRpc;
39+
import com.google.cloud.spanner.spi.v1.SpannerRpc.Option;
3940
import com.google.common.annotations.VisibleForTesting;
4041
import com.google.common.base.Preconditions;
4142
import com.google.common.collect.ImmutableMap;
@@ -45,7 +46,6 @@
4546
import com.google.spanner.v1.DirectedReadOptions;
4647
import com.google.spanner.v1.ExecuteBatchDmlRequest;
4748
import com.google.spanner.v1.ExecuteSqlRequest;
48-
import com.google.spanner.v1.ExecuteSqlRequest.Builder;
4949
import com.google.spanner.v1.ExecuteSqlRequest.QueryMode;
5050
import com.google.spanner.v1.ExecuteSqlRequest.QueryOptions;
5151
import com.google.spanner.v1.PartialResultSet;
@@ -69,6 +69,7 @@ abstract class AbstractReadContext
6969

7070
abstract static class Builder<B extends Builder<?, T>, T extends AbstractReadContext> {
7171
private SessionImpl session;
72+
private boolean cancelQueryWhenClientIsClosed;
7273
private SpannerRpc rpc;
7374
private ISpan span;
7475
private TraceWrapper tracer;
@@ -91,6 +92,11 @@ B setSession(SessionImpl session) {
9192
return self();
9293
}
9394

95+
B setCancelQueryWhenClientIsClosed(boolean cancelQueryWhenClientIsClosed) {
96+
this.cancelQueryWhenClientIsClosed = cancelQueryWhenClientIsClosed;
97+
return self();
98+
}
99+
94100
B setRpc(SpannerRpc rpc) {
95101
this.rpc = rpc;
96102
return self();
@@ -184,7 +190,7 @@ static Builder newBuilder() {
184190
@GuardedBy("lock")
185191
private boolean used;
186192

187-
private final Map<SpannerRpc.Option, ?> channelHint;
193+
private Map<SpannerRpc.Option, ?> channelHint;
188194

189195
private SingleReadContext(Builder builder) {
190196
super(builder);
@@ -227,6 +233,16 @@ TransactionSelector getTransactionSelector() {
227233
Map<SpannerRpc.Option, ?> getTransactionChannelHint() {
228234
return channelHint;
229235
}
236+
237+
@Override
238+
boolean prepareRetryOnDifferentGrpcChannel() {
239+
if (session.getIsMultiplexed() && channelHint.get(Option.CHANNEL_HINT) != null) {
240+
long channelHintForTransaction = Option.CHANNEL_HINT.getLong(channelHint) + 1L;
241+
channelHint = optionMap(SessionOption.channelHint(channelHintForTransaction));
242+
return true;
243+
}
244+
return super.prepareRetryOnDifferentGrpcChannel();
245+
}
230246
}
231247

232248
private static void assertTimestampAvailable(boolean available) {
@@ -440,6 +456,7 @@ void initTransaction() {
440456

441457
final Object lock = new Object();
442458
final SessionImpl session;
459+
final boolean cancelQueryWhenClientIsClosed;
443460
final SpannerRpc rpc;
444461
final ExecutorProvider executorProvider;
445462
ISpan span;
@@ -469,6 +486,7 @@ void initTransaction() {
469486

470487
AbstractReadContext(Builder<?, ?> builder) {
471488
this.session = builder.session;
489+
this.cancelQueryWhenClientIsClosed = builder.cancelQueryWhenClientIsClosed;
472490
this.rpc = builder.rpc;
473491
this.defaultPrefetchChunks = builder.defaultPrefetchChunks;
474492
this.defaultQueryOptions = builder.defaultQueryOptions;
@@ -745,11 +763,13 @@ ResultSet executeQueryInternalWithOptions(
745763
span,
746764
tracer,
747765
tracer.createStatementAttributes(statement, options),
766+
session.getErrorHandler(),
748767
rpc.getExecuteQueryRetrySettings(),
749768
rpc.getExecuteQueryRetryableCodes()) {
750769
@Override
751770
CloseableIterator<PartialResultSet> startStream(@Nullable ByteString resumeToken) {
752-
GrpcStreamIterator stream = new GrpcStreamIterator(statement, prefetchChunks);
771+
GrpcStreamIterator stream =
772+
new GrpcStreamIterator(statement, prefetchChunks, cancelQueryWhenClientIsClosed);
753773
if (partitionToken != null) {
754774
request.setPartitionToken(partitionToken);
755775
}
@@ -774,6 +794,11 @@ CloseableIterator<PartialResultSet> startStream(@Nullable ByteString resumeToken
774794
stream.setCall(call, request.getTransaction().hasBegin());
775795
return stream;
776796
}
797+
798+
@Override
799+
boolean prepareIteratorForRetryOnDifferentGrpcChannel() {
800+
return AbstractReadContext.this.prepareRetryOnDifferentGrpcChannel();
801+
}
777802
};
778803
return new GrpcResultSet(
779804
stream, this, options.hasDecodeMode() ? options.decodeMode() : defaultDecodeMode);
@@ -840,6 +865,10 @@ public void close() {
840865
*/
841866
abstract Map<SpannerRpc.Option, ?> getTransactionChannelHint();
842867

868+
boolean prepareRetryOnDifferentGrpcChannel() {
869+
return false;
870+
}
871+
843872
/**
844873
* Returns the transaction tag for this {@link AbstractReadContext} or <code>null</code> if this
845874
* {@link AbstractReadContext} does not have a transaction tag.
@@ -918,11 +947,13 @@ ResultSet readInternalWithOptions(
918947
SpannerImpl.READ,
919948
span,
920949
tracer,
950+
session.getErrorHandler(),
921951
rpc.getReadRetrySettings(),
922952
rpc.getReadRetryableCodes()) {
923953
@Override
924954
CloseableIterator<PartialResultSet> startStream(@Nullable ByteString resumeToken) {
925-
GrpcStreamIterator stream = new GrpcStreamIterator(prefetchChunks);
955+
GrpcStreamIterator stream =
956+
new GrpcStreamIterator(prefetchChunks, cancelQueryWhenClientIsClosed);
926957
TransactionSelector selector = null;
927958
if (resumeToken != null) {
928959
builder.setResumeToken(resumeToken);
@@ -945,6 +976,11 @@ CloseableIterator<PartialResultSet> startStream(@Nullable ByteString resumeToken
945976
stream.setCall(call, /* withBeginTransaction = */ builder.getTransaction().hasBegin());
946977
return stream;
947978
}
979+
980+
@Override
981+
boolean prepareIteratorForRetryOnDifferentGrpcChannel() {
982+
return AbstractReadContext.this.prepareRetryOnDifferentGrpcChannel();
983+
}
948984
};
949985
return new GrpcResultSet(
950986
stream, this, readOptions.hasDecodeMode() ? readOptions.decodeMode() : defaultDecodeMode);

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ public BatchReadOnlyTransaction batchReadOnlyTransaction(TimestampBound bound) {
5454
return new BatchReadOnlyTransactionImpl(
5555
MultiUseReadOnlyTransaction.newBuilder()
5656
.setSession(session)
57+
.setCancelQueryWhenClientIsClosed(true)
5758
.setRpc(sessionClient.getSpanner().getRpc())
5859
.setTimestampBound(bound)
5960
.setDefaultQueryOptions(
@@ -75,6 +76,7 @@ public BatchReadOnlyTransaction batchReadOnlyTransaction(BatchTransactionId batc
7576
return new BatchReadOnlyTransactionImpl(
7677
MultiUseReadOnlyTransaction.newBuilder()
7778
.setSession(session)
79+
.setCancelQueryWhenClientIsClosed(true)
7880
.setRpc(sessionClient.getSpanner().getRpc())
7981
.setTransactionId(batchTransactionId.getTransactionId())
8082
.setTimestamp(batchTransactionId.getTimestamp())
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/*
2+
* Copyright 2024 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.cloud.spanner;
18+
19+
import com.google.api.core.BetaApi;
20+
import javax.annotation.Nonnull;
21+
22+
/**
23+
* The {@link ErrorHandler} interface can be used to implement custom error and retry handling for
24+
* specific cases. The default implementation does nothing and falls back to the standard error and
25+
* retry handling in Gax and the Spanner client.
26+
*/
27+
@BetaApi
28+
interface ErrorHandler {
29+
@Nonnull
30+
Throwable translateException(@Nonnull Throwable exception);
31+
32+
int getMaxAttempts();
33+
34+
class DefaultErrorHandler implements ErrorHandler {
35+
static final DefaultErrorHandler INSTANCE = new DefaultErrorHandler();
36+
37+
private DefaultErrorHandler() {}
38+
39+
@Nonnull
40+
@Override
41+
public Throwable translateException(@Nonnull Throwable exception) {
42+
return exception;
43+
}
44+
45+
@Override
46+
public int getMaxAttempts() {
47+
return 0;
48+
}
49+
}
50+
}

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

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ class GrpcStreamIterator extends AbstractIterator<PartialResultSet>
3838
private static final Logger logger = Logger.getLogger(GrpcStreamIterator.class.getName());
3939
private static final PartialResultSet END_OF_STREAM = PartialResultSet.newBuilder().build();
4040

41-
private final ConsumerImpl consumer = new ConsumerImpl();
41+
private final ConsumerImpl consumer;
4242
private final BlockingQueue<PartialResultSet> stream;
4343
private final Statement statement;
4444

@@ -49,13 +49,15 @@ class GrpcStreamIterator extends AbstractIterator<PartialResultSet>
4949
private SpannerException error;
5050

5151
@VisibleForTesting
52-
GrpcStreamIterator(int prefetchChunks) {
53-
this(null, prefetchChunks);
52+
GrpcStreamIterator(int prefetchChunks, boolean cancelQueryWhenClientIsClosed) {
53+
this(null, prefetchChunks, cancelQueryWhenClientIsClosed);
5454
}
5555

5656
@VisibleForTesting
57-
GrpcStreamIterator(Statement statement, int prefetchChunks) {
57+
GrpcStreamIterator(
58+
Statement statement, int prefetchChunks, boolean cancelQueryWhenClientIsClosed) {
5859
this.statement = statement;
60+
this.consumer = new ConsumerImpl(cancelQueryWhenClientIsClosed);
5961
// One extra to allow for END_OF_STREAM message.
6062
this.stream = new LinkedBlockingQueue<>(prefetchChunks + 1);
6163
}
@@ -136,6 +138,12 @@ private void addToStream(PartialResultSet results) {
136138
}
137139

138140
private class ConsumerImpl implements SpannerRpc.ResultStreamConsumer {
141+
private final boolean cancelQueryWhenClientIsClosed;
142+
143+
ConsumerImpl(boolean cancelQueryWhenClientIsClosed) {
144+
this.cancelQueryWhenClientIsClosed = cancelQueryWhenClientIsClosed;
145+
}
146+
139147
@Override
140148
public void onPartialResultSet(PartialResultSet results) {
141149
addToStream(results);
@@ -168,5 +176,10 @@ public void onError(SpannerException e) {
168176
error = e;
169177
addToStream(END_OF_STREAM);
170178
}
179+
180+
@Override
181+
public boolean cancelQueryWhenClientIsClosed() {
182+
return this.cancelQueryWhenClientIsClosed;
183+
}
171184
}
172185
}

0 commit comments

Comments
 (0)