Skip to content

Commit fa82369

Browse files
authored
JAVA-6055 Implement prose backpressure retryable writes tests (#1929)
The relevant spec changes: - https://github.com/mongodb/specifications/blame/ba14b6bdc1dc695aa9cc20ccf9378592da1b2329/source/retryable-writes/tests/README.md#L265-L418 - See also https://jira.mongodb.org/browse/DRIVERS-3432 for the phrasing fixes for "Test 3 Case 3" JAVA-6055
1 parent b33dca9 commit fa82369

9 files changed

Lines changed: 459 additions & 178 deletions

File tree

driver-core/src/main/com/mongodb/internal/event/CommandListenerMulticaster.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
package com.mongodb.internal.event;
1818

19+
import com.mongodb.annotations.ThreadSafe;
1920
import com.mongodb.event.CommandFailedEvent;
2021
import com.mongodb.event.CommandListener;
2122
import com.mongodb.event.CommandStartedEvent;
@@ -29,7 +30,11 @@
2930
import static com.mongodb.assertions.Assertions.isTrue;
3031
import static java.lang.String.format;
3132

32-
33+
/**
34+
* This {@link CommandListener} is {@linkplain ThreadSafe thread-safe},
35+
* provided that the recipient listeners passed to {@link #CommandListenerMulticaster(List)} are.
36+
*/
37+
@ThreadSafe
3338
final class CommandListenerMulticaster implements CommandListener {
3439
private static final Logger LOGGER = Loggers.getLogger("protocol.event");
3540

driver-core/src/test/functional/com/mongodb/internal/connection/TestCommandListener.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package com.mongodb.internal.connection;
1818

1919
import com.mongodb.MongoTimeoutException;
20+
import com.mongodb.annotations.ThreadSafe;
2021
import com.mongodb.client.TestListener;
2122
import com.mongodb.event.CommandEvent;
2223
import com.mongodb.event.CommandFailedEvent;
@@ -56,6 +57,7 @@
5657
import static org.junit.Assert.assertNull;
5758
import static org.junit.Assert.assertTrue;
5859

60+
@ThreadSafe
5961
public class TestCommandListener implements CommandListener {
6062
private final List<String> eventTypes;
6163
private final List<String> ignoredCommandMonitoringEvents;

driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/ContextProviderTest.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import com.mongodb.ContextProvider;
2020
import com.mongodb.RequestContext;
2121
import com.mongodb.WriteConcern;
22+
import com.mongodb.annotations.NotThreadSafe;
2223
import com.mongodb.event.CommandFailedEvent;
2324
import com.mongodb.event.CommandListener;
2425
import com.mongodb.event.CommandStartedEvent;
@@ -186,6 +187,7 @@ public void contextShouldBeAvailableInCommandEvents() {
186187
}
187188
}
188189

190+
@NotThreadSafe
189191
private static final class TestCommandListener implements CommandListener {
190192
private int numCommandStartedEventsWithExpectedContext;
191193
private int numCommandSucceededEventsWithExpectedContext;

driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/RetryableReadsProseTest.java

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -22,32 +22,27 @@
2222
import org.bson.Document;
2323
import org.junit.jupiter.api.Test;
2424

25-
import java.util.concurrent.ExecutionException;
26-
import java.util.concurrent.TimeoutException;
27-
2825
import static com.mongodb.client.model.Filters.eq;
2926

3027
/**
31-
* See
32-
* <a href="https://github.com/mongodb/specifications/tree/master/source/retryable-reads/tests">Retryable Reads Tests</a>.
28+
* <a href="https://github.com/mongodb/specifications/blob/master/source/retryable-reads/tests/README.md#prose-tests">
29+
* Prose Tests</a>.
3330
*/
3431
final class RetryableReadsProseTest {
3532
/**
36-
* See
37-
* <a href="https://github.com/mongodb/specifications/tree/master/source/retryable-reads/tests#poolclearederror-retryability-test">
38-
* PoolClearedError Retryability Test</a>.
33+
* <a href="https://github.com/mongodb/specifications/blob/master/source/retryable-reads/tests/README.md#1-poolclearederror-retryability-test">
34+
* 1. PoolClearedError Retryability Test</a>.
3935
*/
4036
@Test
41-
void poolClearedExceptionMustBeRetryable() throws InterruptedException, ExecutionException, TimeoutException {
37+
void poolClearedExceptionMustBeRetryable() throws Exception {
4238
RetryableWritesProseTest.poolClearedExceptionMustBeRetryable(
4339
SyncMongoClient::new,
4440
mongoCollection -> mongoCollection.find(eq(0)).iterator().hasNext(), "find", false);
4541
}
4642

4743
/**
48-
* See
49-
* <a href="https://github.com/mongodb/specifications/tree/master/source/retryable-reads/tests#21-retryable-reads-are-retried-on-a-different-mongos-when-one-is-available">
50-
* Retryable Reads Are Retried on a Different mongos When One is Available</a>.
44+
* <a href="https://github.com/mongodb/specifications/blob/master/source/retryable-reads/tests/README.md#21-retryable-reads-are-retried-on-a-different-mongos-when-one-is-available">
45+
* 2.1 Retryable Reads Are Retried on a Different mongos When One is Available</a>.
5146
*/
5247
@Test
5348
void retriesOnDifferentMongosWhenAvailable() {
@@ -61,9 +56,8 @@ void retriesOnDifferentMongosWhenAvailable() {
6156
}
6257

6358
/**
64-
* See
65-
* <a href="https://github.com/mongodb/specifications/tree/master/source/retryable-reads/tests#22-retryable-reads-are-retried-on-the-same-mongos-when-no-others-are-available">
66-
* Retryable Reads Are Retried on the Same mongos When No Others are Available</a>.
59+
* <a href="https://github.com/mongodb/specifications/blob/master/source/retryable-reads/tests/README.md#22-retryable-reads-are-retried-on-the-same-mongos-when-no-others-are-available">
60+
* 2.2 Retryable Reads Are Retried on the Same mongos When No Others are Available</a>.
6761
*/
6862
@Test
6963
void retriesOnSameMongosWhenAnotherNotAvailable() {

driver-reactive-streams/src/test/functional/com/mongodb/reactivestreams/client/RetryableWritesProseTest.java

Lines changed: 47 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -16,68 +16,87 @@
1616

1717
package com.mongodb.reactivestreams.client;
1818

19-
import com.mongodb.client.test.CollectionHelper;
2019
import com.mongodb.reactivestreams.client.syncadapter.SyncMongoClient;
2120
import org.bson.Document;
22-
import org.bson.codecs.DocumentCodec;
23-
import org.junit.jupiter.api.BeforeEach;
21+
import org.junit.jupiter.api.Disabled;
2422
import org.junit.jupiter.api.Test;
2523

26-
import java.util.concurrent.ExecutionException;
27-
import java.util.concurrent.TimeoutException;
28-
2924
/**
30-
* See
31-
* <a href="https://github.com/mongodb/specifications/blob/master/source/retryable-writes/tests/README.md#prose-tests">Retryable Write Prose Tests</a>.
25+
* <a href="https://github.com/mongodb/specifications/blob/master/source/retryable-writes/tests/README.md#prose-tests">
26+
* Prose Tests</a>.
3227
*/
33-
public class RetryableWritesProseTest extends DatabaseTestCase {
34-
private CollectionHelper<Document> collectionHelper;
35-
36-
@BeforeEach
37-
@Override
38-
public void setUp() {
39-
super.setUp();
40-
41-
collectionHelper = new CollectionHelper<>(new DocumentCodec(), collection.getNamespace());
42-
collectionHelper.create();
43-
}
44-
28+
final class RetryableWritesProseTest {
4529
/**
46-
* Prose test #2.
30+
* <a href="https://github.com/mongodb/specifications/blob/master/source/retryable-writes/tests/README.md#2-test-that-drivers-properly-retry-after-encountering-poolclearederrors">
31+
* 2. Test that drivers properly retry after encountering PoolClearedErrors</a>.
4732
*/
4833
@Test
49-
public void poolClearedExceptionMustBeRetryable() throws InterruptedException, ExecutionException, TimeoutException {
34+
void poolClearedExceptionMustBeRetryable() throws Exception {
5035
com.mongodb.client.RetryableWritesProseTest.poolClearedExceptionMustBeRetryable(
5136
SyncMongoClient::new,
5237
mongoCollection -> mongoCollection.insertOne(new Document()), "insert", true);
5338
}
5439

5540
/**
56-
* Prose test #3.
41+
* <a href="https://github.com/mongodb/specifications/blob/master/source/retryable-writes/tests/README.md#3-test-that-drivers-return-the-original-error-after-encountering-a-writeconcernerror-with-a-retryablewriteerror-label">
42+
* 3. Test that drivers return the original error after encountering a WriteConcernError with a RetryableWriteError label</a>.
5743
*/
5844
@Test
59-
public void originalErrorMustBePropagatedIfNoWritesPerformed() throws InterruptedException {
45+
void originalErrorMustBePropagatedIfNoWritesPerformed() throws Exception {
6046
com.mongodb.client.RetryableWritesProseTest.originalErrorMustBePropagatedIfNoWritesPerformed(
6147
SyncMongoClient::new);
6248
}
6349

6450
/**
65-
* Prose test #4.
51+
* <a href="https://github.com/mongodb/specifications/blob/master/source/retryable-writes/tests/README.md#4-test-that-in-a-sharded-cluster-writes-are-retried-on-a-different-mongos-when-one-is-available">
52+
* 4. Test that in a sharded cluster writes are retried on a different mongos when one is available</a>.
6653
*/
6754
@Test
68-
public void retriesOnDifferentMongosWhenAvailable() {
55+
void retriesOnDifferentMongosWhenAvailable() {
6956
com.mongodb.client.RetryableWritesProseTest.retriesOnDifferentMongosWhenAvailable(
7057
SyncMongoClient::new,
7158
mongoCollection -> mongoCollection.insertOne(new Document()), "insert", true);
7259
}
7360

7461
/**
75-
* Prose test #5.
62+
* <a href="https://github.com/mongodb/specifications/blob/master/source/retryable-writes/tests/README.md#5-test-that-in-a-sharded-cluster-writes-are-retried-on-the-same-mongos-when-no-others-are-available">
63+
* 5. Test that in a sharded cluster writes are retried on the same mongos when no others are available</a>.
7664
*/
7765
@Test
78-
public void retriesOnSameMongosWhenAnotherNotAvailable() {
66+
void retriesOnSameMongosWhenAnotherNotAvailable() {
7967
com.mongodb.client.RetryableWritesProseTest.retriesOnSameMongosWhenAnotherNotAvailable(
8068
SyncMongoClient::new,
8169
mongoCollection -> mongoCollection.insertOne(new Document()), "insert", true);
8270
}
71+
72+
/**
73+
* <a href="https://github.com/mongodb/specifications/blob/master/source/retryable-writes/tests/README.md#case-1-test-that-drivers-return-the-correct-error-when-receiving-only-errors-without-nowritesperformed">
74+
* 6. Test error propagation after encountering multiple errors.
75+
* Case 1: Test that drivers return the correct error when receiving only errors without NoWritesPerformed</a>.
76+
*/
77+
@Test
78+
@Disabled("TODO-BACKPRESSURE Valentin Enable when implementing JAVA-6055")
79+
void errorPropagationAfterEncounteringMultipleErrorsCase1() throws Exception {
80+
com.mongodb.client.RetryableWritesProseTest.errorPropagationAfterEncounteringMultipleErrorsCase1(SyncMongoClient::new);
81+
}
82+
83+
/**
84+
* <a href="https://github.com/mongodb/specifications/blob/master/source/retryable-writes/tests/README.md#case-2-test-that-drivers-return-the-correct-error-when-receiving-only-errors-with-nowritesperformed">
85+
* 6. Test error propagation after encountering multiple errors.
86+
* Case 2: Test that drivers return the correct error when receiving only errors with NoWritesPerformed</a>.
87+
*/
88+
@Test
89+
void errorPropagationAfterEncounteringMultipleErrorsCase2() throws Exception {
90+
com.mongodb.client.RetryableWritesProseTest.errorPropagationAfterEncounteringMultipleErrorsCase2(SyncMongoClient::new);
91+
}
92+
93+
/**
94+
* <a href="https://github.com/mongodb/specifications/blob/master/source/retryable-writes/tests/README.md#case-3-test-that-drivers-return-the-correct-error-when-receiving-some-errors-with-nowritesperformed-and-some-without-nowritesperformed">
95+
* 6. Test error propagation after encountering multiple errors.
96+
* Case 3: Test that drivers return the correct error when receiving some errors with NoWritesPerformed and some without NoWritesPerformed</a>.
97+
*/
98+
@Test
99+
void errorPropagationAfterEncounteringMultipleErrorsCase3() throws Exception {
100+
com.mongodb.client.RetryableWritesProseTest.errorPropagationAfterEncounteringMultipleErrorsCase3(SyncMongoClient::new);
101+
}
83102
}

driver-sync/src/test/functional/com/mongodb/client/ContextProviderTest.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import com.mongodb.ContextProvider;
2020
import com.mongodb.RequestContext;
2121
import com.mongodb.WriteConcern;
22+
import com.mongodb.annotations.NotThreadSafe;
2223
import com.mongodb.event.CommandFailedEvent;
2324
import com.mongodb.event.CommandListener;
2425
import com.mongodb.event.CommandStartedEvent;
@@ -206,6 +207,7 @@ public void contextShouldBeAvailableInCommandEvents() {
206207
}
207208
}
208209

210+
@NotThreadSafe
209211
private static final class TestCommandListener implements CommandListener {
210212
private int numCommandStartedEventsWithExpectedContext;
211213
private int numCommandSucceededEventsWithExpectedContext;

driver-sync/src/test/functional/com/mongodb/client/RetryableReadsProseTest.java

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -19,31 +19,26 @@
1919
import org.bson.Document;
2020
import org.junit.jupiter.api.Test;
2121

22-
import java.util.concurrent.ExecutionException;
23-
import java.util.concurrent.TimeoutException;
24-
2522
import static com.mongodb.client.model.Filters.eq;
2623

2724
/**
28-
* See
29-
* <a href="https://github.com/mongodb/specifications/tree/master/source/retryable-reads/tests">Retryable Reads Tests</a>.
25+
* <a href="https://github.com/mongodb/specifications/blob/master/source/retryable-reads/tests/README.md#prose-tests">
26+
* Prose Tests</a>.
3027
*/
3128
final class RetryableReadsProseTest {
3229
/**
33-
* See
34-
* <a href="https://github.com/mongodb/specifications/tree/master/source/retryable-reads/tests#poolclearederror-retryability-test">
35-
* PoolClearedError Retryability Test</a>.
30+
* <a href="https://github.com/mongodb/specifications/blob/master/source/retryable-reads/tests/README.md#1-poolclearederror-retryability-test">
31+
* 1. PoolClearedError Retryability Test</a>.
3632
*/
3733
@Test
38-
void poolClearedExceptionMustBeRetryable() throws InterruptedException, ExecutionException, TimeoutException {
34+
void poolClearedExceptionMustBeRetryable() throws Exception {
3935
RetryableWritesProseTest.poolClearedExceptionMustBeRetryable(MongoClients::create,
4036
mongoCollection -> mongoCollection.find(eq(0)).iterator().hasNext(), "find", false);
4137
}
4238

4339
/**
44-
* See
45-
* <a href="https://github.com/mongodb/specifications/tree/master/source/retryable-reads/tests#21-retryable-reads-are-retried-on-a-different-mongos-when-one-is-available">
46-
* Retryable Reads Are Retried on a Different mongos When One is Available</a>.
40+
* <a href="https://github.com/mongodb/specifications/blob/master/source/retryable-reads/tests/README.md#21-retryable-reads-are-retried-on-a-different-mongos-when-one-is-available">
41+
* 2.1 Retryable Reads Are Retried on a Different mongos When One is Available</a>.
4742
*/
4843
@Test
4944
void retriesOnDifferentMongosWhenAvailable() {
@@ -56,9 +51,8 @@ void retriesOnDifferentMongosWhenAvailable() {
5651
}
5752

5853
/**
59-
* See
60-
* <a href="https://github.com/mongodb/specifications/tree/master/source/retryable-reads/tests#22-retryable-reads-are-retried-on-the-same-mongos-when-no-others-are-available">
61-
* Retryable Reads Are Retried on the Same mongos When No Others are Available</a>.
54+
* <a href="https://github.com/mongodb/specifications/blob/master/source/retryable-reads/tests/README.md#22-retryable-reads-are-retried-on-the-same-mongos-when-no-others-are-available">
55+
* 2.2 Retryable Reads Are Retried on the Same mongos When No Others are Available</a>.
6256
*/
6357
@Test
6458
void retriesOnSameMongosWhenAnotherNotAvailable() {

0 commit comments

Comments
 (0)