Skip to content

ITReadOnlyTxnTest is flaky with multiplexed sessions #3132

@olavloite

Description

@olavloite

Using a min-read-timestamp is not allowed with a multi-use read-only transaction. This is also checked by the ITReadOnlyTxnTest. However, the error that is returned when using multiplexed sessions can be different than the current expectation. The reason is that if the transaction is started before the multiplexed session has been created, the code flow uses a waiter. This waiter will return the error as a SpannerException, while the direct code flow will return an IllegalArgumentException. That causes the following flaky test failure in some cases (note that in a production situation the difference between the two errors are not really relevant, both indicate a programming error that needs to be fixed in code):

[ERROR] Tests run: 11, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 40.88 s <<< FAILURE! -- in com.google.cloud.spanner.it.ITReadOnlyTxnTest
[ERROR] com.google.cloud.spanner.it.ITReadOnlyTxnTest.multiMinReadTimestamp -- Time elapsed: 0.064 s <<< ERROR!
com.google.cloud.spanner.SpannerException: UNKNOWN: Bounded staleness mode MIN_READ_TIMESTAMP is not supported for multi-use read-only transactions. Create a single-use read or read-only transaction instead.
	at com.google.cloud.spanner.SpannerExceptionFactory.newSpannerExceptionPreformatted(SpannerExceptionFactory.java:291)
	at com.google.cloud.spanner.SpannerExceptionFactory.newSpannerExceptionPreformatted(SpannerExceptionFactory.java:297)
	at com.google.cloud.spanner.SpannerExceptionFactory.newSpannerException(SpannerExceptionFactory.java:61)
	at com.google.cloud.spanner.SpannerExceptionFactory.newSpannerException(SpannerExceptionFactory.java:181)
	at com.google.cloud.spanner.SpannerExceptionFactory.newSpannerException(SpannerExceptionFactory.java:110)
	at com.google.cloud.spanner.SpannerExceptionFactory.asSpannerException(SpannerExceptionFactory.java:100)
	at com.google.cloud.spanner.DelayedReadContext.getReadContext(DelayedReadContext.java:47)
	at com.google.cloud.spanner.DelayedReadContext.lambda$executeQuery$6(DelayedReadContext.java:117)
	at com.google.common.base.Suppliers$NonSerializableMemoizingSupplier.get(Suppliers.java:186)
	at com.google.cloud.spanner.ForwardingResultSet.next(ForwardingResultSet.java:59)
	at com.google.cloud.spanner.it.ITReadOnlyTxnTest.multiMinReadTimestamp(ITReadOnlyTxnTest.java:316)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
	at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
	at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
	at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
	at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
	at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
	at org.junit.rules.ExternalResource$1.evaluate(ExternalResource.java:54)
	at org.junit.rules.RunRules.evaluate(RunRules.java:20)
	at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
	at org.junit.runners.Suite.runChild(Suite.java:128)
	at org.junit.runners.Suite.runChild(Suite.java:27)
	at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
	at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
	at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
	at org.apache.maven.surefire.junitcore.JUnitCore.run(JUnitCore.java:49)
	at org.apache.maven.surefire.junitcore.JUnitCoreWrapper.createRequestAndRun(JUnitCoreWrapper.java:120)
	at org.apache.maven.surefire.junitcore.JUnitCoreWrapper.executeLazy(JUnitCoreWrapper.java:105)
	at org.apache.maven.surefire.junitcore.JUnitCoreWrapper.execute(JUnitCoreWrapper.java:77)
	at org.apache.maven.surefire.junitcore.JUnitCoreWrapper.execute(JUnitCoreWrapper.java:69)
	at org.apache.maven.surefire.junitcore.JUnitCoreProvider.invoke(JUnitCoreProvider.java:146)
	at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:385)
	at org.apache.maven.surefire.booter.ForkedBooter.execute(ForkedBooter.java:162)
	at org.apache.maven.surefire.booter.ForkedBooter.run(ForkedBooter.java:507)
	at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:495)
Caused by: java.lang.IllegalArgumentException: Bounded staleness mode MIN_READ_TIMESTAMP is not supported for multi-use read-only transactions. Create a single-use read or read-only transaction instead.
	at com.google.common.base.Preconditions.checkArgument(Preconditions.java:220)
	at com.google.cloud.spanner.AbstractReadContext$MultiUseReadOnlyTransaction.(AbstractReadContext.java:331)
	at com.google.cloud.spanner.AbstractReadContext$MultiUseReadOnlyTransaction$Builder.build(AbstractReadContext.java:305)
	at com.google.cloud.spanner.SessionImpl.readOnlyTransaction(SessionImpl.java:374)
	at com.google.cloud.spanner.DelayedMultiplexedSessionTransaction.lambda$readOnlyTransaction$5(DelayedMultiplexedSessionTransaction.java:119)
	at com.google.api.core.ApiFutures$ApiFunctionToGuavaFunction.apply(ApiFutures.java:396)
	at com.google.common.util.concurrent.AbstractTransformFuture$TransformFuture.doTransform(AbstractTransformFuture.java:254)
	at com.google.common.util.concurrent.AbstractTransformFuture$TransformFuture.doTransform(AbstractTransformFuture.java:244)
	at com.google.common.util.concurrent.AbstractTransformFuture.run(AbstractTransformFuture.java:125)
	at com.google.common.util.concurrent.DirectExecutor.execute(DirectExecutor.java:31)
	at com.google.common.util.concurrent.AbstractFuture.executeListener(AbstractFuture.java:1298)
	at com.google.common.util.concurrent.AbstractFuture.complete(AbstractFuture.java:1059)
	at com.google.common.util.concurrent.AbstractFuture.set(AbstractFuture.java:784)
	at com.google.api.core.AbstractApiFuture$InternalSettableFuture.set(AbstractApiFuture.java:87)
	at com.google.api.core.AbstractApiFuture.set(AbstractApiFuture.java:70)
	at com.google.api.core.SettableApiFuture.set(SettableApiFuture.java:46)
	at com.google.cloud.spanner.MultiplexedSessionDatabaseClient$1.onSessionReady(MultiplexedSessionDatabaseClient.java:215)
	at com.google.cloud.spanner.SessionClient$CreateMultiplexedSessionsRunnable.run(SessionClient.java:310)
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180)
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:750)

Metadata

Metadata

Assignees

Labels

api: spannerIssues related to the googleapis/java-spanner API.type: processA process-related concern. May include testing, release, or the like.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions