Skip to content

Commit 4c1a2da

Browse files
committed

File tree

2 files changed

+186
-0
lines changed

2 files changed

+186
-0
lines changed
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
2+
* Copyright 2008-present MongoDB, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.mongodb.reactivestreams.client;
18+
19+
import com.mongodb.MongoClientSettings;
20+
import com.mongodb.client.MongoClient;
21+
import com.mongodb.reactivestreams.client.syncadapter.SyncMongoClient;
22+
23+
/**
24+
* <a href="https://github.com/mongodb/specifications/blob/master/source/client-backpressure/tests/README.md#prose-tests">
25+
* Prose Tests</a>.
26+
*/
27+
final class BackpressureProseTest extends com.mongodb.client.BackpressureProseTest {
28+
@Override
29+
protected MongoClient createClient(final MongoClientSettings mongoClientSettings) {
30+
return new SyncMongoClient(mongoClientSettings);
31+
}
32+
}
Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
/*
2+
* Copyright 2008-present MongoDB, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.mongodb.client;
18+
19+
import com.mongodb.MongoClientSettings;
20+
import com.mongodb.MongoServerException;
21+
import com.mongodb.internal.connection.TestCommandListener;
22+
import com.mongodb.internal.time.StartTime;
23+
import com.mongodb.lang.Nullable;
24+
import org.bson.BsonDocument;
25+
import org.bson.Document;
26+
import org.junit.jupiter.api.Disabled;
27+
import org.junit.jupiter.api.Test;
28+
29+
import java.time.Duration;
30+
31+
import static com.mongodb.ClusterFixture.serverVersionAtLeast;
32+
import static com.mongodb.MongoException.RETRYABLE_ERROR_LABEL;
33+
import static com.mongodb.MongoException.SYSTEM_OVERLOADED_ERROR_LABEL;
34+
import static com.mongodb.client.Fixture.getDefaultDatabaseName;
35+
import static com.mongodb.client.Fixture.getMongoClientSettings;
36+
import static com.mongodb.client.Fixture.getPrimary;
37+
import static java.lang.String.format;
38+
import static org.junit.jupiter.api.Assertions.assertEquals;
39+
import static org.junit.jupiter.api.Assertions.assertThrows;
40+
import static org.junit.jupiter.api.Assertions.assertTrue;
41+
import static org.junit.jupiter.api.Assumptions.assumeTrue;
42+
43+
/**
44+
* <a href="https://github.com/mongodb/specifications/blob/master/source/client-backpressure/tests/README.md#prose-tests">
45+
* Prose Tests</a>.
46+
*/
47+
public class BackpressureProseTest {
48+
protected MongoClient createClient(final MongoClientSettings mongoClientSettings) {
49+
return MongoClients.create(mongoClientSettings);
50+
}
51+
52+
/**
53+
* <a href="https://github.com/mongodb/specifications/blob/master/source/client-backpressure/tests/README.md#test-1-operation-retry-uses-exponential-backoff">
54+
* Test 1: Operation Retry Uses Exponential Backoff</a>.
55+
*/
56+
@Test
57+
@Disabled("TODO-BACKPRESSURE Valentin Enable when implementing JAVA-5956, JAVA-6117, JAVA-6113, JAVA-6119, JAVA-6141 if PR 1899 is merged")
58+
void operationRetryUsesExponentialBackoff() throws InterruptedException {
59+
assumeTrue(serverVersionAtLeast(4, 4));
60+
BsonDocument configureFailPoint = BsonDocument.parse(
61+
"{\n"
62+
+ " configureFailPoint: 'failCommand',\n"
63+
+ " mode: 'alwaysOn',\n"
64+
+ " data: {\n"
65+
+ " failCommands: ['insert'],\n"
66+
+ " errorCode: 2,\n"
67+
+ " errorLabels: ['" + SYSTEM_OVERLOADED_ERROR_LABEL + "', '" + RETRYABLE_ERROR_LABEL + "']\n"
68+
+ " }\n"
69+
+ "}\n");
70+
try (MongoClient client = createClient(getMongoClientSettings());
71+
FailPoint ignored = FailPoint.enable(configureFailPoint, getPrimary())) {
72+
MongoCollection<Document> collection = dropAndGetCollection("operationRetryUsesExponentialBackoff", client);
73+
long noBackoffTimeMillis = measureFailedInsertDuration(collection, false).toMillis();
74+
long withBackoffTimeMillis = measureFailedInsertDuration(collection, true).toMillis();
75+
long expectedMaxVarianceMillis = 300;
76+
long maxTotalBackoffMillis = 300;
77+
long actualAbsDiffMillis = Math.abs(withBackoffTimeMillis - (noBackoffTimeMillis + maxTotalBackoffMillis));
78+
assertTrue(actualAbsDiffMillis < expectedMaxVarianceMillis,
79+
format("Expected actualAbsDiffMillis < %d ms, but was %d ms (|%d ms - (%d ms + %d ms)|)",
80+
expectedMaxVarianceMillis, actualAbsDiffMillis, withBackoffTimeMillis, noBackoffTimeMillis, maxTotalBackoffMillis));
81+
}
82+
}
83+
84+
private static Duration measureFailedInsertDuration(final MongoCollection<Document> collection, final boolean retryBackoff) {
85+
if (!retryBackoff) {
86+
// TODO-BACKPRESSURE Valentin uncomment below when https://github.com/mongodb/mongo-java-driver/pull/1899 is merged
87+
// ExponentialBackoff.setTestJitterSupplier(() -> 0);
88+
}
89+
try {
90+
StartTime startTime = StartTime.now();
91+
assertThrows(MongoServerException.class, () -> collection.insertOne(Document.parse("{a: 1}")));
92+
return startTime.elapsed();
93+
} finally {
94+
// TODO-BACKPRESSURE Valentin uncomment below when https://github.com/mongodb/mongo-java-driver/pull/1899 is merged
95+
// ExponentialBackoff.clearTestJitterSupplier();
96+
}
97+
}
98+
99+
/**
100+
* <a href="https://github.com/mongodb/specifications/blob/master/source/client-backpressure/tests/README.md#test-3-overload-errors-are-retried-a-maximum-of-max_retries-times">
101+
* Test 3: Overload Errors are Retried a Maximum of {@code MAX_RETRIES} times</a>.
102+
*/
103+
@Test
104+
@Disabled("TODO-BACKPRESSURE Valentin Enable when implementing JAVA-5956, JAVA-6117, JAVA-6113, JAVA-6119, JAVA-6141")
105+
void overloadErrorsAreRetriedAtMostMaxRetriesTimes() throws InterruptedException {
106+
overloadErrorsAreRetriedLimitedNumberOfTimes(null);
107+
}
108+
109+
/**
110+
* <a href="https://github.com/mongodb/specifications/blob/master/source/client-backpressure/tests/README.md#test-4-overload-errors-are-retried-a-maximum-of-maxadaptiveretries-times-when-configured">
111+
* Test 4: Overload Errors are Retried a Maximum of {@code maxAdaptiveRetries} times when configured</a>.
112+
*/
113+
@Test
114+
@Disabled("TODO-BACKPRESSURE Valentin Enable when implementing JAVA-5956, JAVA-6117, JAVA-6113, JAVA-6119, JAVA-6141")
115+
void overloadErrorsAreRetriedAtMostMaxAdaptiveRetriesTimesWhenConfigured() throws InterruptedException {
116+
overloadErrorsAreRetriedLimitedNumberOfTimes(1);
117+
}
118+
119+
private void overloadErrorsAreRetriedLimitedNumberOfTimes(@Nullable final Integer maxAdaptiveRetries)
120+
throws InterruptedException {
121+
assumeTrue(serverVersionAtLeast(4, 4));
122+
TestCommandListener commandListener = new TestCommandListener();
123+
BsonDocument configureFailPoint = BsonDocument.parse(
124+
"{\n"
125+
+ " configureFailPoint: 'failCommand',\n"
126+
+ " mode: 'alwaysOn',\n"
127+
+ " data: {\n"
128+
+ " failCommands: ['find'],\n"
129+
+ " errorCode: 462,\n"
130+
+ " errorLabels: ['" + SYSTEM_OVERLOADED_ERROR_LABEL + "', '" + RETRYABLE_ERROR_LABEL + "']\n"
131+
+ " }\n"
132+
+ "}\n");
133+
// TODO-BACKPRESSURE Valentin replace 2 with `MAX_RETRIES` when implementing JAVA-5956, JAVA-6117, JAVA-6113, JAVA-6119, JAVA-6141
134+
int expectedAttempts = (maxAdaptiveRetries == null ? 2 : maxAdaptiveRetries) + 1;
135+
try (MongoClient client = createClient(MongoClientSettings.builder(getMongoClientSettings())
136+
.maxAdaptiveRetries(maxAdaptiveRetries)
137+
.addCommandListener(commandListener)
138+
.build());
139+
FailPoint ignored = FailPoint.enable(configureFailPoint, getPrimary())) {
140+
MongoCollection<Document> collection = dropAndGetCollection("overloadErrorsAreRetriedLimitedNumberOfTimes", client);
141+
commandListener.reset();
142+
MongoServerException exception = assertThrows(MongoServerException.class, () -> collection.find().first());
143+
assertTrue(exception.hasErrorLabel(SYSTEM_OVERLOADED_ERROR_LABEL));
144+
assertTrue(exception.hasErrorLabel(RETRYABLE_ERROR_LABEL));
145+
assertEquals(expectedAttempts, commandListener.getCommandStartedEvents().size());
146+
}
147+
}
148+
149+
private static MongoCollection<Document> dropAndGetCollection(final String name, final MongoClient client) {
150+
MongoCollection<Document> result = client.getDatabase(getDefaultDatabaseName()).getCollection(name);
151+
result.drop();
152+
return result;
153+
}
154+
}

0 commit comments

Comments
 (0)