Skip to content

Commit cf416b3

Browse files
vbabaninrozza
andauthored
Use connectTimeoutMS for connection establishment in maintenance TimeoutContext. (#1777)
JAVA-5927 --------- Co-authored-by: Ross Lawley <[email protected]> Co-authored-by: Ross Lawley <[email protected]>
1 parent 6e897c8 commit cf416b3

File tree

4 files changed

+73
-3
lines changed

4 files changed

+73
-3
lines changed

driver-core/src/main/com/mongodb/internal/TimeoutContext.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,10 @@ public long getWriteTimeoutMS() {
289289

290290
public int getConnectTimeoutMs() {
291291
final long connectTimeoutMS = getTimeoutSettings().getConnectTimeoutMS();
292+
if (isMaintenanceContext) {
293+
return (int) connectTimeoutMS;
294+
}
295+
292296
return Math.toIntExact(Timeout.nullAsInfinite(timeout).call(MILLISECONDS,
293297
() -> connectTimeoutMS,
294298
(ms) -> connectTimeoutMS == 0 ? ms : Math.min(ms, connectTimeoutMS),

driver-core/src/main/com/mongodb/internal/connection/SocksSocket.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -81,11 +81,11 @@ public SocksSocket(@Nullable final Socket socket, final ProxySettings proxySetti
8181
}
8282

8383
@Override
84-
public void connect(final SocketAddress endpoint, final int timeoutMs) throws IOException {
84+
public void connect(final SocketAddress endpoint, final int connectTimeoutMs) throws IOException {
8585
// `Socket` requires `IllegalArgumentException`
86-
isTrueArgument("timeoutMs", timeoutMs >= 0);
86+
isTrueArgument("connectTimeoutMs", connectTimeoutMs >= 0);
8787
try {
88-
Timeout timeout = Timeout.expiresIn(timeoutMs, MILLISECONDS, ZERO_DURATION_MEANS_INFINITE);
88+
Timeout timeout = Timeout.expiresIn(connectTimeoutMs, MILLISECONDS, ZERO_DURATION_MEANS_INFINITE);
8989
InetSocketAddress unresolvedAddress = (InetSocketAddress) endpoint;
9090
assertTrue(unresolvedAddress.isUnresolved());
9191
this.remoteAddress = unresolvedAddress;

driver-core/src/test/functional/com/mongodb/internal/connection/SocketStreamHelperSpecification.groovy

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,11 @@ package com.mongodb.internal.connection
1818

1919
import com.mongodb.ClusterFixture
2020
import com.mongodb.MongoInternalException
21+
import com.mongodb.MongoOperationTimeoutException
2122
import com.mongodb.connection.SocketSettings
2223
import com.mongodb.connection.SslSettings
24+
import com.mongodb.internal.TimeoutContext
25+
import com.mongodb.internal.TimeoutSettings
2326
import jdk.net.ExtendedSocketOptions
2427
import spock.lang.IgnoreIf
2528
import spock.lang.Specification
@@ -78,6 +81,30 @@ class SocketStreamHelperSpecification extends Specification {
7881
socket?.close()
7982
}
8083
84+
def 'should throw MongoOperationTimeoutException during initialization when timeoutMS expires'() {
85+
given:
86+
Socket socket = SocketFactory.default.createSocket()
87+
88+
when:
89+
SocketStreamHelper.initialize(
90+
OPERATION_CONTEXT.withTimeoutContext(new TimeoutContext(
91+
new TimeoutSettings(
92+
1,
93+
100,
94+
100,
95+
1,
96+
100))),
97+
socket, getSocketAddresses(getPrimary(), new DefaultInetAddressResolver()).get(0),
98+
SocketSettings.builder().build(), SslSettings.builder().build())
99+
100+
then:
101+
thrown(MongoOperationTimeoutException)
102+
103+
cleanup:
104+
socket?.close()
105+
}
106+
107+
81108
def 'should connect socket()'() {
82109
given:
83110
Socket socket = SocketFactory.default.createSocket()

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

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
import com.mongodb.event.ConnectionClosedEvent;
4848
import com.mongodb.event.ConnectionCreatedEvent;
4949
import com.mongodb.event.ConnectionReadyEvent;
50+
import com.mongodb.internal.connection.InternalStreamConnection;
5051
import com.mongodb.internal.connection.ServerHelper;
5152
import com.mongodb.internal.connection.TestCommandListener;
5253
import com.mongodb.internal.connection.TestConnectionPoolListener;
@@ -1018,6 +1019,44 @@ public void shouldThrowTimeoutExceptionForSubsequentCommitTransaction() {
10181019
assertEquals(1, failedEvents.size());
10191020
}
10201021

1022+
/**
1023+
* Not a prose spec test. However, it is additional test case for better coverage.
1024+
* <p>
1025+
* From the spec:
1026+
* - When doing `minPoolSize` maintenance, `connectTimeoutMS` is used as the timeout for socket establishment.
1027+
*/
1028+
@Test
1029+
@DisplayName("Should use connectTimeoutMS when establishing connection in background")
1030+
public void shouldUseConnectTimeoutMsWhenEstablishingConnectionInBackground() {
1031+
assumeTrue(serverVersionAtLeast(4, 4));
1032+
1033+
collectionHelper.runAdminCommand("{"
1034+
+ "configureFailPoint: \"" + FAIL_COMMAND_NAME + "\","
1035+
+ "mode: \"alwaysOn\","
1036+
+ " data: {"
1037+
+ " failCommands: [\"hello\", \"isMaster\"],"
1038+
+ " blockConnection: true,"
1039+
+ " blockTimeMS: " + 500
1040+
+ " }"
1041+
+ "}");
1042+
1043+
try (MongoClient ignored = createMongoClient(getMongoClientSettingsBuilder()
1044+
.applyToConnectionPoolSettings(builder -> builder.minSize(1))
1045+
// Use a very short timeout to ensure that the connection establishment will fail on the first handshake command.
1046+
.timeout(10, TimeUnit.MILLISECONDS))) {
1047+
InternalStreamConnection.setRecordEverything(true);
1048+
1049+
// Wait for the connection to start establishment in the background.
1050+
sleep(1000);
1051+
} finally {
1052+
InternalStreamConnection.setRecordEverything(false);
1053+
}
1054+
1055+
List<CommandFailedEvent> commandFailedEvents = commandListener.getCommandFailedEvents("isMaster");
1056+
assertEquals(1, commandFailedEvents.size());
1057+
assertInstanceOf(MongoOperationTimeoutException.class, commandFailedEvents.get(0).getThrowable());
1058+
}
1059+
10211060
private static Stream<Arguments> test8ServerSelectionArguments() {
10221061
return Stream.of(
10231062
Arguments.of(Named.of("serverSelectionTimeoutMS honored if timeoutMS is not set",

0 commit comments

Comments
 (0)