|
17 | 17 | package com.google.cloud.spanner;
|
18 | 18 |
|
19 | 19 | import static com.google.cloud.spanner.SpannerExceptionFactory.newSpannerException;
|
20 |
| -import static com.google.common.base.Preconditions.checkNotNull; |
21 | 20 |
|
22 | 21 | import com.google.api.core.ApiFuture;
|
23 | 22 | import com.google.api.core.SettableApiFuture;
|
|
28 | 27 | import com.google.cloud.spanner.AbstractReadContext.SingleUseReadOnlyTransaction;
|
29 | 28 | import com.google.cloud.spanner.Options.TransactionOption;
|
30 | 29 | import com.google.cloud.spanner.Options.UpdateOption;
|
31 |
| -import com.google.cloud.spanner.SessionClient.SessionId; |
32 | 30 | import com.google.cloud.spanner.TransactionRunnerImpl.TransactionContextImpl;
|
33 | 31 | import com.google.cloud.spanner.spi.v1.SpannerRpc;
|
34 | 32 | import com.google.common.base.Ticker;
|
@@ -97,49 +95,23 @@ interface SessionTransaction {
|
97 | 95 | }
|
98 | 96 |
|
99 | 97 | private final SpannerImpl spanner;
|
100 |
| -private final String name; |
101 |
| -private final DatabaseId databaseId; |
| 98 | +private final SessionReference sessionReference; |
102 | 99 | private SessionTransaction activeTransaction;
|
103 |
| -private final Map<SpannerRpc.Option, ?> options; |
104 |
| -private volatile Instant lastUseTime; |
105 |
| -@Nullable private final Instant createTime; |
106 |
| -private final boolean isMultiplexed; |
107 | 100 | private ISpan currentSpan;
|
108 | 101 |
|
109 |
| -SessionImpl(SpannerImpl spanner, String name, Map<SpannerRpc.Option, ?> options) { |
| 102 | +SessionImpl(SpannerImpl spanner, SessionReference sessionReference) { |
110 | 103 | this.spanner = spanner;
|
111 | 104 | this.tracer = spanner.getTracer();
|
112 |
| -this.options = options; |
113 |
| -this.name = checkNotNull(name); |
114 |
| -this.databaseId = SessionId.of(name).getDatabaseId(); |
115 |
| -this.lastUseTime = Instant.now(); |
116 |
| -this.createTime = null; |
117 |
| -this.isMultiplexed = false; |
118 |
| -} |
119 |
| - |
120 |
| -SessionImpl( |
121 |
| -SpannerImpl spanner, |
122 |
| -String name, |
123 |
| -com.google.protobuf.Timestamp createTime, |
124 |
| -boolean isMultiplexed, |
125 |
| -Map<SpannerRpc.Option, ?> options) { |
126 |
| -this.spanner = spanner; |
127 |
| -this.tracer = spanner.getTracer(); |
128 |
| -this.options = options; |
129 |
| -this.name = checkNotNull(name); |
130 |
| -this.databaseId = SessionId.of(name).getDatabaseId(); |
131 |
| -this.lastUseTime = Instant.now(); |
132 |
| -this.createTime = convert(createTime); |
133 |
| -this.isMultiplexed = isMultiplexed; |
| 105 | +this.sessionReference = sessionReference; |
134 | 106 | }
|
135 | 107 |
|
136 | 108 | @Override
|
137 | 109 | public String getName() {
|
138 |
| -return name; |
| 110 | +return sessionReference.getName(); |
139 | 111 | }
|
140 | 112 |
|
141 | 113 | Map<SpannerRpc.Option, ?> getOptions() {
|
142 |
| -return options; |
| 114 | +return sessionReference.getOptions(); |
143 | 115 | }
|
144 | 116 |
|
145 | 117 | void setCurrentSpan(ISpan span) {
|
@@ -151,19 +123,27 @@ ISpan getCurrentSpan() {
|
151 | 123 | }
|
152 | 124 |
|
153 | 125 | Instant getLastUseTime() {
|
154 |
| -return lastUseTime; |
| 126 | +return sessionReference.getLastUseTime(); |
155 | 127 | }
|
156 | 128 |
|
157 | 129 | Instant getCreateTime() {
|
158 |
| -return createTime; |
| 130 | +return sessionReference.getCreateTime(); |
159 | 131 | }
|
160 | 132 |
|
161 | 133 | boolean getIsMultiplexed() {
|
162 |
| -return isMultiplexed; |
| 134 | +return sessionReference.getIsMultiplexed(); |
| 135 | +} |
| 136 | + |
| 137 | +SessionReference getSessionReference() { |
| 138 | +return sessionReference; |
163 | 139 | }
|
164 | 140 |
|
165 | 141 | void markUsed(Instant instant) {
|
166 |
| -lastUseTime = instant; |
| 142 | +sessionReference.markUsed(instant); |
| 143 | +} |
| 144 | + |
| 145 | +public DatabaseId getDatabaseId() { |
| 146 | +return sessionReference.getDatabaseId(); |
167 | 147 | }
|
168 | 148 |
|
169 | 149 | @Override
|
@@ -211,7 +191,7 @@ public CommitResponse writeAtLeastOnceWithOptions(
|
211 | 191 | Options options = Options.fromTransactionOptions(transactionOptions);
|
212 | 192 | final CommitRequest.Builder requestBuilder =
|
213 | 193 | CommitRequest.newBuilder()
|
214 |
| -.setSession(name) |
| 194 | +.setSession(getName()) |
215 | 195 | .setReturnCommitStats(options.withCommitStats())
|
216 | 196 | .addAllMutations(mutationsProto);
|
217 | 197 |
|
@@ -239,7 +219,7 @@ public CommitResponse writeAtLeastOnceWithOptions(
|
239 | 219 | ISpan span = tracer.spanBuilder(SpannerImpl.COMMIT);
|
240 | 220 | try (IScope s = tracer.withSpan(span)) {
|
241 | 221 | return SpannerRetryHelper.runTxWithRetriesOnAborted(
|
242 |
| -() -> new CommitResponse(spanner.getRpc().commit(request, this.options))); |
| 222 | +() -> new CommitResponse(spanner.getRpc().commit(request, getOptions()))); |
243 | 223 | } catch (RuntimeException e) {
|
244 | 224 | span.setStatus(e);
|
245 | 225 | throw e;
|
@@ -271,7 +251,9 @@ public ServerStream<BatchWriteResponse> batchWriteAtLeastOnce(
|
271 | 251 | List<BatchWriteRequest.MutationGroup> mutationGroupsProto =
|
272 | 252 | MutationGroup.toListProto(mutationGroups);
|
273 | 253 | final BatchWriteRequest.Builder requestBuilder =
|
274 |
| -BatchWriteRequest.newBuilder().setSession(name).addAllMutationGroups(mutationGroupsProto); |
| 254 | +BatchWriteRequest.newBuilder() |
| 255 | +.setSession(getName()) |
| 256 | +.addAllMutationGroups(mutationGroupsProto); |
275 | 257 | RequestOptions batchWriteRequestOptions = getRequestOptions(transactionOptions);
|
276 | 258 | if (batchWriteRequestOptions != null) {
|
277 | 259 | requestBuilder.setRequestOptions(batchWriteRequestOptions);
|
@@ -282,7 +264,7 @@ public ServerStream<BatchWriteResponse> batchWriteAtLeastOnce(
|
282 | 264 | }
|
283 | 265 | ISpan span = tracer.spanBuilder(SpannerImpl.BATCH_WRITE);
|
284 | 266 | try (IScope s = tracer.withSpan(span)) {
|
285 |
| -return spanner.getRpc().batchWriteAtLeastOnce(requestBuilder.build(), this.options); |
| 267 | +return spanner.getRpc().batchWriteAtLeastOnce(requestBuilder.build(), getOptions()); |
286 | 268 | } catch (Throwable e) {
|
287 | 269 | span.setStatus(e);
|
288 | 270 | throw SpannerExceptionFactory.newSpannerException(e);
|
@@ -303,7 +285,7 @@ public ReadContext singleUse(TimestampBound bound) {
|
303 | 285 | .setSession(this)
|
304 | 286 | .setTimestampBound(bound)
|
305 | 287 | .setRpc(spanner.getRpc())
|
306 |
| -.setDefaultQueryOptions(spanner.getDefaultQueryOptions(databaseId)) |
| 288 | +.setDefaultQueryOptions(spanner.getDefaultQueryOptions(getDatabaseId())) |
307 | 289 | .setDefaultPrefetchChunks(spanner.getDefaultPrefetchChunks())
|
308 | 290 | .setDefaultDecodeMode(spanner.getDefaultDecodeMode())
|
309 | 291 | .setDefaultDirectedReadOptions(spanner.getOptions().getDirectedReadOptions())
|
@@ -325,7 +307,7 @@ public ReadOnlyTransaction singleUseReadOnlyTransaction(TimestampBound bound) {
|
325 | 307 | .setSession(this)
|
326 | 308 | .setTimestampBound(bound)
|
327 | 309 | .setRpc(spanner.getRpc())
|
328 |
| -.setDefaultQueryOptions(spanner.getDefaultQueryOptions(databaseId)) |
| 310 | +.setDefaultQueryOptions(spanner.getDefaultQueryOptions(getDatabaseId())) |
329 | 311 | .setDefaultPrefetchChunks(spanner.getDefaultPrefetchChunks())
|
330 | 312 | .setDefaultDecodeMode(spanner.getDefaultDecodeMode())
|
331 | 313 | .setDefaultDirectedReadOptions(spanner.getOptions().getDirectedReadOptions())
|
@@ -347,7 +329,7 @@ public ReadOnlyTransaction readOnlyTransaction(TimestampBound bound) {
|
347 | 329 | .setSession(this)
|
348 | 330 | .setTimestampBound(bound)
|
349 | 331 | .setRpc(spanner.getRpc())
|
350 |
| -.setDefaultQueryOptions(spanner.getDefaultQueryOptions(databaseId)) |
| 332 | +.setDefaultQueryOptions(spanner.getDefaultQueryOptions(getDatabaseId())) |
351 | 333 | .setDefaultPrefetchChunks(spanner.getDefaultPrefetchChunks())
|
352 | 334 | .setDefaultDecodeMode(spanner.getDefaultDecodeMode())
|
353 | 335 | .setDefaultDirectedReadOptions(spanner.getOptions().getDirectedReadOptions())
|
@@ -379,14 +361,14 @@ public AsyncTransactionManagerImpl transactionManagerAsync(TransactionOption...
|
379 | 361 |
|
380 | 362 | @Override
|
381 | 363 | public ApiFuture<Empty> asyncClose() {
|
382 |
| -return spanner.getRpc().asyncDeleteSession(name, options); |
| 364 | +return spanner.getRpc().asyncDeleteSession(getName(), getOptions()); |
383 | 365 | }
|
384 | 366 |
|
385 | 367 | @Override
|
386 | 368 | public void close() {
|
387 | 369 | ISpan span = tracer.spanBuilder(SpannerImpl.DELETE_SESSION);
|
388 | 370 | try (IScope s = tracer.withSpan(span)) {
|
389 |
| -spanner.getRpc().deleteSession(name, options); |
| 371 | +spanner.getRpc().deleteSession(getName(), getOptions()); |
390 | 372 | } catch (RuntimeException e) {
|
391 | 373 | span.setStatus(e);
|
392 | 374 | throw e;
|
@@ -400,11 +382,11 @@ ApiFuture<ByteString> beginTransactionAsync(Options transactionOptions, boolean
|
400 | 382 | final ISpan span = tracer.spanBuilder(SpannerImpl.BEGIN_TRANSACTION);
|
401 | 383 | final BeginTransactionRequest request =
|
402 | 384 | BeginTransactionRequest.newBuilder()
|
403 |
| -.setSession(name) |
| 385 | +.setSession(getName()) |
404 | 386 | .setOptions(createReadWriteTransactionOptions(transactionOptions))
|
405 | 387 | .build();
|
406 | 388 | final ApiFuture<Transaction> requestFuture =
|
407 |
| -spanner.getRpc().beginTransactionAsync(request, options, routeToLeader); |
| 389 | +spanner.getRpc().beginTransactionAsync(request, getOptions(), routeToLeader); |
408 | 390 | requestFuture.addListener(
|
409 | 391 | () -> {
|
410 | 392 | try (IScope s = tracer.withSpan(span)) {
|
@@ -446,7 +428,7 @@ TransactionContextImpl newTransaction(Options options) {
|
446 | 428 | .setOptions(options)
|
447 | 429 | .setTrackTransactionStarter(spanner.getOptions().isTrackTransactionStarter())
|
448 | 430 | .setRpc(spanner.getRpc())
|
449 |
| -.setDefaultQueryOptions(spanner.getDefaultQueryOptions(databaseId)) |
| 431 | +.setDefaultQueryOptions(spanner.getDefaultQueryOptions(getDatabaseId())) |
450 | 432 | .setDefaultPrefetchChunks(spanner.getDefaultPrefetchChunks())
|
451 | 433 | .setDefaultDecodeMode(spanner.getDefaultDecodeMode())
|
452 | 434 | .setSpan(currentSpan)
|
@@ -458,9 +440,11 @@ TransactionContextImpl newTransaction(Options options) {
|
458 | 440 |
|
459 | 441 | <T extends SessionTransaction> T setActive(@Nullable T ctx) {
|
460 | 442 | throwIfTransactionsPending();
|
461 |
| - |
462 |
| -if (activeTransaction != null) { |
463 |
| -activeTransaction.invalidate(); |
| 443 | +// multiplexed sessions support running concurrent transactions |
| 444 | +if (!getIsMultiplexed()) { |
| 445 | +if (activeTransaction != null) { |
| 446 | +activeTransaction.invalidate(); |
| 447 | +} |
464 | 448 | }
|
465 | 449 | activeTransaction = ctx;
|
466 | 450 | if (activeTransaction != null) {
|
@@ -472,11 +456,4 @@ <T extends SessionTransaction> T setActive(@Nullable T ctx) {
|
472 | 456 | TraceWrapper getTracer() {
|
473 | 457 | return tracer;
|
474 | 458 | }
|
475 |
| - |
476 |
| -private Instant convert(com.google.protobuf.Timestamp timestamp) { |
477 |
| -if (timestamp == null) { |
478 |
| -return null; |
479 |
| -} |
480 |
| -return Instant.ofEpochSecond(timestamp.getSeconds(), timestamp.getNanos()); |
481 |
| -} |
482 | 459 | }
|
0 commit comments