Skip to content

Commit 9d3479b

Browse files
authored
fix(6.4.4-sp): sessions were not always removed from checkedOutSessions (#1445)
* fix: sessions were not always removed from checkedOutSessions Sessions were added to a set of checked out sessions when one was checked out from the session pool. When the session was released back to the pool, the session would normally be removed from the set of checked out sessions. The latter would not always happen if the application that checked out the session did not use the session for any reads or writes. chore: fix maven version to 3.8.1 chore: fix maven version for windows * test: skip slow tests on stable branch * test: try to add compile workflow to see if build succeeds * test: add compile job instead of file
1 parent 5c19547 commit 9d3479b

File tree

6 files changed

+137
-17
lines changed

6 files changed

+137
-17
lines changed

.github/workflows/ci.yaml

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ jobs:
1414
- 11
1515
steps:
1616
- uses: actions/checkout@v2
17+
- uses: stCarolas/setup-maven@v4
18+
with:
19+
maven-version: 3.8.1
1720
- uses: actions/setup-java@v1
1821
with:
1922
java-version: ${{matrix.java}}
@@ -25,6 +28,9 @@ jobs:
2528
runs-on: windows-latest
2629
steps:
2730
- uses: actions/checkout@v2
31+
- uses: stCarolas/setup-maven@v4
32+
with:
33+
maven-version: 3.8.1
2834
- uses: actions/setup-java@v1
2935
with:
3036
java-version: 8
@@ -41,6 +47,9 @@ jobs:
4147
- 11
4248
steps:
4349
- uses: actions/checkout@v2
50+
- uses: stCarolas/setup-maven@v4
51+
with:
52+
maven-version: 3.8.1
4453
- uses: actions/setup-java@v1
4554
with:
4655
java-version: ${{matrix.java}}
@@ -50,6 +59,9 @@ jobs:
5059
runs-on: ubuntu-latest
5160
steps:
5261
- uses: actions/checkout@v2
62+
- uses: stCarolas/setup-maven@v4
63+
with:
64+
maven-version: 3.8.1
5365
- uses: actions/setup-java@v1
5466
with:
5567
java-version: 8
@@ -61,10 +73,32 @@ jobs:
6173
runs-on: ubuntu-latest
6274
steps:
6375
- uses: actions/checkout@v2
76+
- uses: stCarolas/setup-maven@v4
77+
with:
78+
maven-version: 3.8.1
6479
- uses: actions/setup-java@v1
6580
with:
6681
java-version: 8
6782
- run: java -version
6883
- run: .kokoro/build.sh
6984
env:
7085
JOB_TYPE: clirr
86+
compile:
87+
runs-on: ubuntu-latest
88+
strategy:
89+
matrix:
90+
java:
91+
- 8
92+
- 11
93+
steps:
94+
- uses: actions/checkout@v2
95+
- uses: stCarolas/setup-maven@v4
96+
with:
97+
maven-version: 3.8.1
98+
- uses: actions/setup-java@v1
99+
with:
100+
java-version: ${{matrix.java}}
101+
- run: java -version
102+
- run: mvn package
103+
env:
104+
JOB_TYPE: test

.github/workflows/integration-tests-against-emulator.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ jobs:
1515
- '9020:9020'
1616
steps:
1717
- uses: actions/checkout@v2
18+
- uses: stCarolas/setup-maven@v4
19+
with:
20+
maven-version: 3.8.1
1821
- uses: actions/setup-java@v1
1922
with:
2023
java-version: 8

.github/workflows/samples.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ jobs:
66
runs-on: ubuntu-latest
77
steps:
88
- uses: actions/checkout@v2
9+
- uses: stCarolas/setup-maven@v4
10+
with:
11+
maven-version: 3.8.1
912
- uses: actions/setup-java@v1
1013
with:
1114
java-version: 8

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

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1240,25 +1240,27 @@ public void prepareReadWriteTransaction() {
12401240

12411241
@Override
12421242
public void close() {
1243-
synchronized (lock) {
1244-
leakedException = null;
1245-
checkedOutSessions.remove(this);
1246-
}
1247-
PooledSession delegate = getOrNull();
1248-
if (delegate != null) {
1249-
delegate.close();
1243+
try {
1244+
asyncClose().get();
1245+
} catch (InterruptedException e) {
1246+
throw SpannerExceptionFactory.propagateInterrupt(e);
1247+
} catch (ExecutionException e) {
1248+
throw SpannerExceptionFactory.asSpannerException(e.getCause());
12501249
}
12511250
}
12521251

12531252
@Override
12541253
public ApiFuture<Empty> asyncClose() {
1255-
synchronized (lock) {
1256-
leakedException = null;
1257-
checkedOutSessions.remove(this);
1258-
}
1259-
PooledSession delegate = getOrNull();
1260-
if (delegate != null) {
1261-
return delegate.asyncClose();
1254+
try {
1255+
PooledSession delegate = getOrNull();
1256+
if (delegate != null) {
1257+
return delegate.asyncClose();
1258+
}
1259+
} finally {
1260+
synchronized (lock) {
1261+
leakedException = null;
1262+
checkedOutSessions.remove(this);
1263+
}
12621264
}
12631265
return ApiFutures.immediateFuture(Empty.getDefaultInstance());
12641266
}
@@ -1767,7 +1769,8 @@ private enum Position {
17671769
private final Set<PooledSession> allSessions = new HashSet<>();
17681770

17691771
@GuardedBy("lock")
1770-
private final Set<PooledSessionFuture> checkedOutSessions = new HashSet<>();
1772+
@VisibleForTesting
1773+
final Set<PooledSessionFuture> checkedOutSessions = new HashSet<>();
17711774

17721775
private final SessionConsumer sessionConsumer = new SessionConsumerImpl();
17731776

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

Lines changed: 75 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@
6969
import java.util.ArrayList;
7070
import java.util.Collections;
7171
import java.util.List;
72+
import java.util.Set;
7273
import java.util.concurrent.ExecutionException;
7374
import java.util.concurrent.ExecutorService;
7475
import java.util.concurrent.Executors;
@@ -534,13 +535,18 @@ public void testAsyncTransactionManagerCommitWithTag() {
534535

535536
@Test
536537
public void singleUse() {
537-
DatabaseClient client =
538-
spanner.getDatabaseClient(DatabaseId.of(TEST_PROJECT, TEST_INSTANCE, TEST_DATABASE));
538+
DatabaseClientImpl client =
539+
(DatabaseClientImpl)
540+
spanner.getDatabaseClient(DatabaseId.of(TEST_PROJECT, TEST_INSTANCE, TEST_DATABASE));
541+
Set<PooledSessionFuture> checkedOut = client.pool.checkedOutSessions;
542+
assertThat(checkedOut).isEmpty();
539543
try (ResultSet rs = client.singleUse().executeQuery(SELECT1)) {
540544
assertThat(rs.next()).isTrue();
545+
assertThat(checkedOut).hasSize(1);
541546
assertThat(rs.getLong(0)).isEqualTo(1L);
542547
assertThat(rs.next()).isFalse();
543548
}
549+
assertThat(checkedOut).isEmpty();
544550
}
545551

546552
@Test
@@ -2076,4 +2082,71 @@ public void testAsyncTransactionManagerCommitWithPriority() {
20762082
assertNotNull(request.getRequestOptions());
20772083
assertEquals(Priority.PRIORITY_HIGH, request.getRequestOptions().getPriority());
20782084
}
2085+
2086+
@Test
2087+
public void singleUseNoAction_ClearsCheckedOutSession() {
2088+
DatabaseClientImpl client =
2089+
(DatabaseClientImpl)
2090+
spanner.getDatabaseClient(DatabaseId.of(TEST_PROJECT, TEST_INSTANCE, TEST_DATABASE));
2091+
Set<PooledSessionFuture> checkedOut = client.pool.checkedOutSessions;
2092+
assertThat(checkedOut).isEmpty();
2093+
2094+
// Getting a single use read-only transaction and not using it should not cause any sessions
2095+
// to be stuck in the map of checked out sessions.
2096+
client.singleUse().close();
2097+
2098+
assertThat(checkedOut).isEmpty();
2099+
}
2100+
2101+
@Test
2102+
public void singleUseReadOnlyTransactionNoAction_ClearsCheckedOutSession() {
2103+
DatabaseClientImpl client =
2104+
(DatabaseClientImpl)
2105+
spanner.getDatabaseClient(DatabaseId.of(TEST_PROJECT, TEST_INSTANCE, TEST_DATABASE));
2106+
Set<PooledSessionFuture> checkedOut = client.pool.checkedOutSessions;
2107+
assertThat(checkedOut).isEmpty();
2108+
2109+
client.singleUseReadOnlyTransaction().close();
2110+
2111+
assertThat(checkedOut).isEmpty();
2112+
}
2113+
2114+
@Test
2115+
public void readWriteTransactionNoAction_ClearsCheckedOutSession() {
2116+
DatabaseClientImpl client =
2117+
(DatabaseClientImpl)
2118+
spanner.getDatabaseClient(DatabaseId.of(TEST_PROJECT, TEST_INSTANCE, TEST_DATABASE));
2119+
Set<PooledSessionFuture> checkedOut = client.pool.checkedOutSessions;
2120+
assertThat(checkedOut).isEmpty();
2121+
2122+
client.readWriteTransaction();
2123+
2124+
assertThat(checkedOut).isEmpty();
2125+
}
2126+
2127+
@Test
2128+
public void readOnlyTransactionNoAction_ClearsCheckedOutSession() {
2129+
DatabaseClientImpl client =
2130+
(DatabaseClientImpl)
2131+
spanner.getDatabaseClient(DatabaseId.of(TEST_PROJECT, TEST_INSTANCE, TEST_DATABASE));
2132+
Set<PooledSessionFuture> checkedOut = client.pool.checkedOutSessions;
2133+
assertThat(checkedOut).isEmpty();
2134+
2135+
client.readOnlyTransaction().close();
2136+
2137+
assertThat(checkedOut).isEmpty();
2138+
}
2139+
2140+
@Test
2141+
public void transactionManagerNoAction_ClearsCheckedOutSession() {
2142+
DatabaseClientImpl client =
2143+
(DatabaseClientImpl)
2144+
spanner.getDatabaseClient(DatabaseId.of(TEST_PROJECT, TEST_INSTANCE, TEST_DATABASE));
2145+
Set<PooledSessionFuture> checkedOut = client.pool.checkedOutSessions;
2146+
assertThat(checkedOut).isEmpty();
2147+
2148+
client.transactionManager().close();
2149+
2150+
assertThat(checkedOut).isEmpty();
2151+
}
20792152
}

google-cloud-spanner/src/test/java/com/google/cloud/spanner/it/ITBackupTest.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@
7676
import org.junit.Before;
7777
import org.junit.BeforeClass;
7878
import org.junit.ClassRule;
79+
import org.junit.Ignore;
7980
import org.junit.Test;
8081
import org.junit.experimental.categories.Category;
8182
import org.junit.runner.RunWith;
@@ -206,6 +207,7 @@ private void waitForDbOperations(String backupId) throws InterruptedException {
206207
}
207208

208209
@Test
210+
@Ignore("Do not run slow test in stable branch")
209211
public void testBackups() throws InterruptedException, ExecutionException {
210212
// Create two test databases in parallel.
211213
final String db1Id = testHelper.getUniqueDatabaseId() + "_db1";
@@ -383,6 +385,7 @@ public void testBackups() throws InterruptedException, ExecutionException {
383385
}
384386

385387
@Test(expected = SpannerException.class)
388+
@Ignore("Do not run slow test in stable branch")
386389
public void backupCreationWithVersionTimeTooFarInThePastFails() throws Exception {
387390
final Database testDatabase = testHelper.createTestDatabase();
388391
final DatabaseId databaseId = testDatabase.getId();
@@ -402,6 +405,7 @@ public void backupCreationWithVersionTimeTooFarInThePastFails() throws Exception
402405
}
403406

404407
@Test(expected = SpannerException.class)
408+
@Ignore("Do not run slow test in stable branch")
405409
public void backupCreationWithVersionTimeInTheFutureFails() throws Exception {
406410
final Database testDatabase = testHelper.createTestDatabase();
407411
final DatabaseId databaseId = testDatabase.getId();

0 commit comments

Comments
 (0)