Skip to content

Commit abdf020

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

File tree

3 files changed

+70
-18
lines changed

3 files changed

+70
-18
lines changed

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: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,18 @@
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;
2124
import static org.junit.Assert.assertTrue;
25+
import static org.mockito.Mockito.mock;
26+
import static org.mockito.Mockito.when;
2227

28+
import com.google.cloud.NoCredentials;
2329
import com.google.spanner.v1.BeginTransactionRequest;
2430
import com.google.spanner.v1.ExecuteSqlRequest;
31+
import io.grpc.ManagedChannelBuilder;
2532
import java.util.concurrent.CountDownLatch;
2633
import java.util.concurrent.TimeUnit;
2734
import org.junit.Test;
@@ -148,4 +155,40 @@ public void testMultipleQueriesOnlyCallsBeginTransactionOnce() throws Exception
148155
BeginTransactionRequest.class, ExecuteSqlRequest.class, ExecuteSqlRequest.class);
149156
}
150157
}
158+
159+
@Test(timeout = 5000)
160+
public void createAsyncResultSet_handlesExceptionCorrectly() throws Exception {
161+
SpannerOptions.CloseableExecutorProvider mockExecutorProvider =
162+
mock(SpannerOptions.CloseableExecutorProvider.class);
163+
when(mockExecutorProvider.getExecutor())
164+
.thenThrow(new RuntimeException("Failed to get executor"));
165+
166+
String endpoint = address.getHostString() + ":" + server.getPort();
167+
SpannerOptions options =
168+
SpannerOptions.newBuilder()
169+
.setProjectId(TEST_PROJECT)
170+
.setChannelConfigurator(ManagedChannelBuilder::usePlaintext)
171+
.setHost("http://" + endpoint)
172+
.setCredentials(NoCredentials.getInstance())
173+
.setAsyncExecutorProvider(mockExecutorProvider)
174+
.setSessionPoolOption(
175+
SessionPoolOptions.newBuilder()
176+
.setFailOnSessionLeak()
177+
.setWaitForMinSessions(org.threeten.bp.Duration.ofSeconds(2))
178+
.build())
179+
.build();
180+
181+
try (Spanner testSpanner = options.getService()) {
182+
DatabaseClient client =
183+
testSpanner.getDatabaseClient(DatabaseId.of(TEST_PROJECT, TEST_INSTANCE, TEST_DATABASE));
184+
try (ReadOnlyTransaction transaction = client.readOnlyTransaction()) {
185+
try {
186+
transaction.executeQueryAsync(READ_ONE_KEY_VALUE_STATEMENT);
187+
org.junit.Assert.fail("Expected RuntimeException");
188+
} catch (RuntimeException e) {
189+
assertThat(e.getMessage()).isEqualTo("Failed to get executor");
190+
}
191+
}
192+
}
193+
}
151194
}

0 commit comments

Comments
 (0)