Skip to content

Commit 0611d07

Browse files
authored
Merge branch 'main' into main
2 parents eb25e67 + 9940b66 commit 0611d07

File tree

24 files changed

+629
-172
lines changed

24 files changed

+629
-172
lines changed

benchmarks/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
<parent>
2525
<groupId>com.google.cloud</groupId>
2626
<artifactId>google-cloud-spanner-parent</artifactId>
27-
<version>6.89.0</version><!-- {x-version-update:google-cloud-spanner:current} -->
27+
<version>6.89.1-SNAPSHOT</version><!-- {x-version-update:google-cloud-spanner:current} -->
2828
</parent>
2929

3030
<properties>

google-cloud-spanner-bom/pom.xml

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<modelVersion>4.0.0</modelVersion>
44
<groupId>com.google.cloud</groupId>
55
<artifactId>google-cloud-spanner-bom</artifactId>
6-
<version>6.89.0</version><!-- {x-version-update:google-cloud-spanner:current} -->
6+
<version>6.89.1-SNAPSHOT</version><!-- {x-version-update:google-cloud-spanner:current} -->
77
<packaging>pom</packaging>
88
<parent>
99
<groupId>com.google.cloud</groupId>
@@ -53,43 +53,43 @@
5353
<dependency>
5454
<groupId>com.google.cloud</groupId>
5555
<artifactId>google-cloud-spanner</artifactId>
56-
<version>6.89.0</version><!-- {x-version-update:google-cloud-spanner:current} -->
56+
<version>6.89.1-SNAPSHOT</version><!-- {x-version-update:google-cloud-spanner:current} -->
5757
</dependency>
5858
<dependency>
5959
<groupId>com.google.cloud</groupId>
6060
<artifactId>google-cloud-spanner</artifactId>
6161
<type>test-jar</type>
62-
<version>6.89.0</version><!-- {x-version-update:google-cloud-spanner:current} -->
62+
<version>6.89.1-SNAPSHOT</version><!-- {x-version-update:google-cloud-spanner:current} -->
6363
</dependency>
6464
<dependency>
6565
<groupId>com.google.api.grpc</groupId>
6666
<artifactId>grpc-google-cloud-spanner-v1</artifactId>
67-
<version>6.89.0</version><!-- {x-version-update:grpc-google-cloud-spanner-v1:current} -->
67+
<version>6.89.1-SNAPSHOT</version><!-- {x-version-update:grpc-google-cloud-spanner-v1:current} -->
6868
</dependency>
6969
<dependency>
7070
<groupId>com.google.api.grpc</groupId>
7171
<artifactId>grpc-google-cloud-spanner-admin-instance-v1</artifactId>
72-
<version>6.89.0</version><!-- {x-version-update:grpc-google-cloud-spanner-admin-instance-v1:current} -->
72+
<version>6.89.1-SNAPSHOT</version><!-- {x-version-update:grpc-google-cloud-spanner-admin-instance-v1:current} -->
7373
</dependency>
7474
<dependency>
7575
<groupId>com.google.api.grpc</groupId>
7676
<artifactId>grpc-google-cloud-spanner-admin-database-v1</artifactId>
77-
<version>6.89.0</version><!-- {x-version-update:grpc-google-cloud-spanner-admin-database-v1:current} -->
77+
<version>6.89.1-SNAPSHOT</version><!-- {x-version-update:grpc-google-cloud-spanner-admin-database-v1:current} -->
7878
</dependency>
7979
<dependency>
8080
<groupId>com.google.api.grpc</groupId>
8181
<artifactId>proto-google-cloud-spanner-admin-instance-v1</artifactId>
82-
<version>6.89.0</version><!-- {x-version-update:proto-google-cloud-spanner-admin-instance-v1:current} -->
82+
<version>6.89.1-SNAPSHOT</version><!-- {x-version-update:proto-google-cloud-spanner-admin-instance-v1:current} -->
8383
</dependency>
8484
<dependency>
8585
<groupId>com.google.api.grpc</groupId>
8686
<artifactId>proto-google-cloud-spanner-v1</artifactId>
87-
<version>6.89.0</version><!-- {x-version-update:proto-google-cloud-spanner-v1:current} -->
87+
<version>6.89.1-SNAPSHOT</version><!-- {x-version-update:proto-google-cloud-spanner-v1:current} -->
8888
</dependency>
8989
<dependency>
9090
<groupId>com.google.api.grpc</groupId>
9191
<artifactId>proto-google-cloud-spanner-admin-database-v1</artifactId>
92-
<version>6.89.0</version><!-- {x-version-update:proto-google-cloud-spanner-admin-database-v1:current} -->
92+
<version>6.89.1-SNAPSHOT</version><!-- {x-version-update:proto-google-cloud-spanner-admin-database-v1:current} -->
9393
</dependency>
9494
</dependencies>
9595
</dependencyManagement>

google-cloud-spanner-executor/pom.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@
55
<modelVersion>4.0.0</modelVersion>
66
<groupId>com.google.cloud</groupId>
77
<artifactId>google-cloud-spanner-executor</artifactId>
8-
<version>6.89.0</version><!-- {x-version-update:google-cloud-spanner-executor:current} -->
8+
<version>6.89.1-SNAPSHOT</version><!-- {x-version-update:google-cloud-spanner-executor:current} -->
99
<packaging>jar</packaging>
1010
<name>Google Cloud Spanner Executor</name>
1111

1212
<parent>
1313
<groupId>com.google.cloud</groupId>
1414
<artifactId>google-cloud-spanner-parent</artifactId>
15-
<version>6.89.0</version><!-- {x-version-update:google-cloud-spanner:current} -->
15+
<version>6.89.1-SNAPSHOT</version><!-- {x-version-update:google-cloud-spanner:current} -->
1616
</parent>
1717

1818
<properties>

google-cloud-spanner/pom.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,15 @@
33
<modelVersion>4.0.0</modelVersion>
44
<groupId>com.google.cloud</groupId>
55
<artifactId>google-cloud-spanner</artifactId>
6-
<version>6.89.0</version><!-- {x-version-update:google-cloud-spanner:current} -->
6+
<version>6.89.1-SNAPSHOT</version><!-- {x-version-update:google-cloud-spanner:current} -->
77
<packaging>jar</packaging>
88
<name>Google Cloud Spanner</name>
99
<url>https://github.com/googleapis/java-spanner</url>
1010
<description>Java idiomatic client for Google Cloud Spanner.</description>
1111
<parent>
1212
<groupId>com.google.cloud</groupId>
1313
<artifactId>google-cloud-spanner-parent</artifactId>
14-
<version>6.89.0</version><!-- {x-version-update:google-cloud-spanner:current} -->
14+
<version>6.89.1-SNAPSHOT</version><!-- {x-version-update:google-cloud-spanner:current} -->
1515
</parent>
1616
<properties>
1717
<site.installationModule>google-cloud-spanner</site.installationModule>

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

Lines changed: 61 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -404,6 +404,32 @@ ByteString getTransactionId() {
404404
}
405405
}
406406

407+
/**
408+
* Initializes the transaction with the timestamp specified within MultiUseReadOnlyTransaction.
409+
* This is used only for fallback of PartitionQueryRequest and PartitionReadRequest with
410+
* Multiplexed Session.
411+
*/
412+
void initFallbackTransaction() {
413+
synchronized (txnLock) {
414+
span.addAnnotation("Creating Transaction");
415+
TransactionOptions.Builder options = TransactionOptions.newBuilder();
416+
if (timestamp != null) {
417+
options
418+
.getReadOnlyBuilder()
419+
.setReadTimestamp(timestamp.toProto())
420+
.setReturnReadTimestamp(true);
421+
} else {
422+
bound.applyToBuilder(options.getReadOnlyBuilder()).setReturnReadTimestamp(true);
423+
}
424+
final BeginTransactionRequest request =
425+
BeginTransactionRequest.newBuilder()
426+
.setSession(session.getName())
427+
.setOptions(options)
428+
.build();
429+
initTransactionInternal(request);
430+
}
431+
}
432+
407433
void initTransaction() {
408434
SessionImpl.throwIfTransactionsPending();
409435

@@ -419,40 +445,43 @@ void initTransaction() {
419445
return;
420446
}
421447
span.addAnnotation("Creating Transaction");
448+
TransactionOptions.Builder options = TransactionOptions.newBuilder();
449+
bound.applyToBuilder(options.getReadOnlyBuilder()).setReturnReadTimestamp(true);
450+
final BeginTransactionRequest request =
451+
BeginTransactionRequest.newBuilder()
452+
.setSession(session.getName())
453+
.setOptions(options)
454+
.build();
455+
initTransactionInternal(request);
456+
}
457+
}
458+
459+
private void initTransactionInternal(BeginTransactionRequest request) {
460+
try {
461+
Transaction transaction =
462+
rpc.beginTransaction(request, getTransactionChannelHint(), isRouteToLeader());
463+
if (!transaction.hasReadTimestamp()) {
464+
throw SpannerExceptionFactory.newSpannerException(
465+
ErrorCode.INTERNAL, "Missing expected transaction.read_timestamp metadata field");
466+
}
467+
if (transaction.getId().isEmpty()) {
468+
throw SpannerExceptionFactory.newSpannerException(
469+
ErrorCode.INTERNAL, "Missing expected transaction.id metadata field");
470+
}
422471
try {
423-
TransactionOptions.Builder options = TransactionOptions.newBuilder();
424-
bound.applyToBuilder(options.getReadOnlyBuilder()).setReturnReadTimestamp(true);
425-
final BeginTransactionRequest request =
426-
BeginTransactionRequest.newBuilder()
427-
.setSession(session.getName())
428-
.setOptions(options)
429-
.build();
430-
Transaction transaction =
431-
rpc.beginTransaction(request, getTransactionChannelHint(), isRouteToLeader());
432-
if (!transaction.hasReadTimestamp()) {
433-
throw SpannerExceptionFactory.newSpannerException(
434-
ErrorCode.INTERNAL, "Missing expected transaction.read_timestamp metadata field");
435-
}
436-
if (transaction.getId().isEmpty()) {
437-
throw SpannerExceptionFactory.newSpannerException(
438-
ErrorCode.INTERNAL, "Missing expected transaction.id metadata field");
439-
}
440-
try {
441-
timestamp = Timestamp.fromProto(transaction.getReadTimestamp());
442-
} catch (IllegalArgumentException e) {
443-
throw SpannerExceptionFactory.newSpannerException(
444-
ErrorCode.INTERNAL, "Bad value in transaction.read_timestamp metadata field", e);
445-
}
446-
transactionId = transaction.getId();
447-
span.addAnnotation(
448-
"Transaction Creation Done",
449-
ImmutableMap.of(
450-
"Id", transaction.getId().toStringUtf8(), "Timestamp", timestamp.toString()));
451-
452-
} catch (SpannerException e) {
453-
span.addAnnotation("Transaction Creation Failed", e);
454-
throw e;
472+
timestamp = Timestamp.fromProto(transaction.getReadTimestamp());
473+
} catch (IllegalArgumentException e) {
474+
throw SpannerExceptionFactory.newSpannerException(
475+
ErrorCode.INTERNAL, "Bad value in transaction.read_timestamp metadata field", e);
455476
}
477+
transactionId = transaction.getId();
478+
span.addAnnotation(
479+
"Transaction Creation Done",
480+
ImmutableMap.of(
481+
"Id", transaction.getId().toStringUtf8(), "Timestamp", timestamp.toString()));
482+
} catch (SpannerException e) {
483+
span.addAnnotation("Transaction Creation Failed", e);
484+
throw e;
456485
}
457486
}
458487
}

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

Lines changed: 56 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,8 @@ public BatchReadOnlyTransaction batchReadOnlyTransaction(TimestampBound bound) {
114114
sessionClient.getSpanner().getOptions().getDirectedReadOptions())
115115
.setSpan(sessionClient.getSpanner().getTracer().getCurrentSpan())
116116
.setTracer(sessionClient.getSpanner().getTracer()),
117-
checkNotNull(bound));
117+
checkNotNull(bound),
118+
sessionClient);
118119
}
119120

120121
@Override
@@ -137,7 +138,8 @@ public BatchReadOnlyTransaction batchReadOnlyTransaction(BatchTransactionId batc
137138
sessionClient.getSpanner().getOptions().getDirectedReadOptions())
138139
.setSpan(sessionClient.getSpanner().getTracer().getCurrentSpan())
139140
.setTracer(sessionClient.getSpanner().getTracer()),
140-
batchTransactionId);
141+
batchTransactionId,
142+
sessionClient);
141143
}
142144

143145
private boolean canUseMultiplexedSession() {
@@ -160,20 +162,28 @@ private SessionImpl getMultiplexedSession() {
160162

161163
private static class BatchReadOnlyTransactionImpl extends MultiUseReadOnlyTransaction
162164
implements BatchReadOnlyTransaction {
163-
private final String sessionName;
165+
private String sessionName;
164166
private final Map<SpannerRpc.Option, ?> options;
167+
private final SessionClient sessionClient;
168+
private final AtomicBoolean fallbackInitiated = new AtomicBoolean(false);
165169

166170
BatchReadOnlyTransactionImpl(
167-
MultiUseReadOnlyTransaction.Builder builder, TimestampBound bound) {
171+
MultiUseReadOnlyTransaction.Builder builder,
172+
TimestampBound bound,
173+
SessionClient sessionClient) {
168174
super(builder.setTimestampBound(bound));
175+
this.sessionClient = sessionClient;
169176
this.sessionName = session.getName();
170177
this.options = session.getOptions();
171178
initTransaction();
172179
}
173180

174181
BatchReadOnlyTransactionImpl(
175-
MultiUseReadOnlyTransaction.Builder builder, BatchTransactionId batchTransactionId) {
182+
MultiUseReadOnlyTransaction.Builder builder,
183+
BatchTransactionId batchTransactionId,
184+
SessionClient sessionClient) {
176185
super(builder.setTransactionId(batchTransactionId.getTransactionId()));
186+
this.sessionClient = sessionClient;
177187
this.sessionName = session.getName();
178188
this.options = session.getOptions();
179189
}
@@ -204,6 +214,18 @@ public List<Partition> partitionReadUsingIndex(
204214
Iterable<String> columns,
205215
ReadOption... option)
206216
throws SpannerException {
217+
return partitionReadUsingIndex(partitionOptions, table, index, keys, columns, false, option);
218+
}
219+
220+
private List<Partition> partitionReadUsingIndex(
221+
PartitionOptions partitionOptions,
222+
String table,
223+
String index,
224+
KeySet keys,
225+
Iterable<String> columns,
226+
boolean isFallback,
227+
ReadOption... option)
228+
throws SpannerException {
207229
Options readOptions = Options.fromReadOptions(option);
208230
Preconditions.checkArgument(
209231
!readOptions.hasLimit(),
@@ -246,7 +268,10 @@ public List<Partition> partitionReadUsingIndex(
246268
}
247269
return partitions.build();
248270
} catch (SpannerException e) {
249-
maybeMarkUnimplementedForPartitionedOps(e);
271+
if (!isFallback && maybeMarkUnimplementedForPartitionedOps(e)) {
272+
return partitionReadUsingIndex(
273+
partitionOptions, table, index, keys, columns, true, option);
274+
}
250275
throw e;
251276
}
252277
}
@@ -255,6 +280,15 @@ public List<Partition> partitionReadUsingIndex(
255280
public List<Partition> partitionQuery(
256281
PartitionOptions partitionOptions, Statement statement, QueryOption... option)
257282
throws SpannerException {
283+
return partitionQuery(partitionOptions, statement, false, option);
284+
}
285+
286+
private List<Partition> partitionQuery(
287+
PartitionOptions partitionOptions,
288+
Statement statement,
289+
boolean isFallback,
290+
QueryOption... option)
291+
throws SpannerException {
258292
Options queryOptions = Options.fromQueryOptions(option);
259293
final PartitionQueryRequest.Builder builder =
260294
PartitionQueryRequest.newBuilder().setSession(sessionName).setSql(statement.getSql());
@@ -291,16 +325,29 @@ public List<Partition> partitionQuery(
291325
}
292326
return partitions.build();
293327
} catch (SpannerException e) {
294-
maybeMarkUnimplementedForPartitionedOps(e);
328+
if (!isFallback && maybeMarkUnimplementedForPartitionedOps(e)) {
329+
return partitionQuery(partitionOptions, statement, true, option);
330+
}
295331
throw e;
296332
}
297333
}
298334

299-
void maybeMarkUnimplementedForPartitionedOps(SpannerException spannerException) {
335+
boolean maybeMarkUnimplementedForPartitionedOps(SpannerException spannerException) {
300336
if (MultiplexedSessionDatabaseClient.verifyErrorMessage(
301337
spannerException, "Partitioned operations are not supported with multiplexed sessions")) {
302-
unimplementedForPartitionedOps.set(true);
338+
synchronized (fallbackInitiated) {
339+
if (!fallbackInitiated.get()) {
340+
session.setFallbackSessionReference(
341+
sessionClient.createSession().getSessionReference());
342+
sessionName = session.getName();
343+
initFallbackTransaction();
344+
unimplementedForPartitionedOps.set(true);
345+
fallbackInitiated.set(true);
346+
}
347+
return true;
348+
}
303349
}
350+
return false;
304351
}
305352

306353
@Override

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package com.google.cloud.spanner;
1818

1919
import com.google.cloud.Timestamp;
20+
import com.google.common.annotations.VisibleForTesting;
2021
import com.google.common.base.Preconditions;
2122
import com.google.protobuf.ByteString;
2223
import java.io.Serializable;
@@ -34,6 +35,7 @@ public class BatchTransactionId implements Serializable {
3435
private final Timestamp timestamp;
3536
private static final long serialVersionUID = 8067099123096783939L;
3637

38+
@VisibleForTesting
3739
BatchTransactionId(String sessionId, ByteString transactionId, Timestamp timestamp) {
3840
this.transactionId = Preconditions.checkNotNull(transactionId);
3941
this.sessionId = Preconditions.checkNotNull(sessionId);

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

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,14 +44,17 @@ class DelayedMultiplexedSessionTransaction extends AbstractMultiplexedSessionDat
4444
private final ISpan span;
4545

4646
private final ApiFuture<SessionReference> sessionFuture;
47+
private final SessionPool sessionPool;
4748

4849
DelayedMultiplexedSessionTransaction(
4950
MultiplexedSessionDatabaseClient client,
5051
ISpan span,
51-
ApiFuture<SessionReference> sessionFuture) {
52+
ApiFuture<SessionReference> sessionFuture,
53+
SessionPool sessionPool) {
5254
this.client = client;
5355
this.span = span;
5456
this.sessionFuture = sessionFuture;
57+
this.sessionPool = sessionPool;
5558
}
5659

5760
@Override
@@ -189,7 +192,12 @@ public TransactionRunner readWriteTransaction(TransactionOption... options) {
189192
this.sessionFuture,
190193
sessionReference ->
191194
new MultiplexedSessionTransaction(
192-
client, span, sessionReference, NO_CHANNEL_HINT, /* singleUse = */ false)
195+
client,
196+
span,
197+
sessionReference,
198+
NO_CHANNEL_HINT,
199+
/* singleUse = */ false,
200+
this.sessionPool)
193201
.readWriteTransaction(options),
194202
MoreExecutors.directExecutor()));
195203
}

0 commit comments

Comments
 (0)