Skip to content

Commit 92e7777

Browse files
committed
chore(spanner): address review comment
1 parent 6a2c9db commit 92e7777

3 files changed

Lines changed: 71 additions & 18 deletions

File tree

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

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -414,26 +414,35 @@ TransactionSelector getTransactionSelector() {
414414
return selector;
415415
}
416416

417+
private void decrementPendingStartsAndSignal() {
418+
if (pendingStarts.decrementAndGet() == 0) {
419+
txnLock.lock();
420+
try {
421+
hasNoPendingStarts.signalAll();
422+
} finally {
423+
txnLock.unlock();
424+
}
425+
}
426+
}
427+
417428
private ListenableAsyncResultSet createAsyncResultSet(
418429
Supplier<ResultSet> resultSetSupplier, int bufferRows) {
419430
pendingStarts.incrementAndGet();
420-
return new AsyncResultSetImpl(
421-
executorProvider,
422-
() -> {
423-
try {
424-
return resultSetSupplier.get();
425-
} finally {
426-
if (pendingStarts.decrementAndGet() == 0) {
427-
txnLock.lock();
428-
try {
429-
hasNoPendingStarts.signalAll();
430-
} finally {
431-
txnLock.unlock();
432-
}
431+
try {
432+
return new AsyncResultSetImpl(
433+
executorProvider,
434+
() -> {
435+
try {
436+
return resultSetSupplier.get();
437+
} finally {
438+
decrementPendingStartsAndSignal();
433439
}
434-
}
435-
},
436-
bufferRows);
440+
},
441+
bufferRows);
442+
} catch (Throwable t) {
443+
decrementPendingStartsAndSignal();
444+
throw t;
445+
}
437446
}
438447

439448
@Override

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,8 @@
4747
/** Base class for {@link AsyncRunnerTest} and {@link AsyncTransactionManagerTest}. */
4848
public abstract class AbstractAsyncTransactionTest {
4949
static MockSpannerServiceImpl mockSpanner;
50-
private static Server server;
51-
private static InetSocketAddress address;
50+
static Server server;
51+
static InetSocketAddress address;
5252
static ExecutorService executor;
5353

5454
Spanner spanner;

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

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

1919
import static com.google.cloud.spanner.MockSpannerTestUtil.READ_ONE_KEY_VALUE_STATEMENT;
20+
import static com.google.cloud.spanner.MockSpannerTestUtil.TEST_DATABASE;
21+
import static com.google.cloud.spanner.MockSpannerTestUtil.TEST_INSTANCE;
22+
import static com.google.cloud.spanner.MockSpannerTestUtil.TEST_PROJECT;
2023
import static com.google.common.truth.Truth.assertThat;
24+
import static org.junit.Assert.assertEquals;
25+
import static org.junit.Assert.assertThrows;
2126
import static org.junit.Assert.assertTrue;
27+
import static org.mockito.Mockito.mock;
28+
import static org.mockito.Mockito.when;
2229

30+
import com.google.cloud.NoCredentials;
2331
import com.google.spanner.v1.BeginTransactionRequest;
2432
import com.google.spanner.v1.ExecuteSqlRequest;
33+
import io.grpc.ManagedChannelBuilder;
2534
import java.util.concurrent.CountDownLatch;
2635
import java.util.concurrent.TimeUnit;
2736
import org.junit.Test;
@@ -148,4 +157,39 @@ public void testMultipleQueriesOnlyCallsBeginTransactionOnce() throws Exception
148157
BeginTransactionRequest.class, ExecuteSqlRequest.class, ExecuteSqlRequest.class);
149158
}
150159
}
160+
161+
@Test(timeout = 5000)
162+
public void createAsyncResultSet_handlesExceptionCorrectly() throws Exception {
163+
SpannerOptions.CloseableExecutorProvider mockExecutorProvider =
164+
mock(SpannerOptions.CloseableExecutorProvider.class);
165+
when(mockExecutorProvider.getExecutor())
166+
.thenThrow(new RuntimeException("Failed to get executor"));
167+
168+
String endpoint = address.getHostString() + ":" + server.getPort();
169+
SpannerOptions options =
170+
SpannerOptions.newBuilder()
171+
.setProjectId(TEST_PROJECT)
172+
.setChannelConfigurator(ManagedChannelBuilder::usePlaintext)
173+
.setHost("http://" + endpoint)
174+
.setCredentials(NoCredentials.getInstance())
175+
.setAsyncExecutorProvider(mockExecutorProvider)
176+
.setSessionPoolOption(
177+
SessionPoolOptions.newBuilder()
178+
.setFailOnSessionLeak()
179+
.setWaitForMinSessions(org.threeten.bp.Duration.ofSeconds(2))
180+
.build())
181+
.build();
182+
183+
try (Spanner testSpanner = options.getService()) {
184+
DatabaseClient client =
185+
testSpanner.getDatabaseClient(DatabaseId.of(TEST_PROJECT, TEST_INSTANCE, TEST_DATABASE));
186+
try (ReadOnlyTransaction transaction = client.readOnlyTransaction()) {
187+
RuntimeException e =
188+
assertThrows(
189+
RuntimeException.class,
190+
() -> transaction.executeQueryAsync(READ_ONE_KEY_VALUE_STATEMENT));
191+
assertEquals("Failed to get executor", e.getMessage());
192+
}
193+
}
194+
}
151195
}

0 commit comments

Comments
 (0)