From bcc22ba0afe2f383cda26f2a45b216edc8c3c156 Mon Sep 17 00:00:00 2001 From: Nathan Xu Date: Fri, 18 Oct 2024 09:59:01 -0400 Subject: [PATCH 1/6] Allow valid SRV hostnames with less than 3 parts (#1534) --- .../crud/aggregate-write-readPreference.json | 69 ------------------- .../db-aggregate-write-readPreference.json | 51 -------------- 2 files changed, 120 deletions(-) diff --git a/driver-core/src/test/resources/unified-test-format/crud/aggregate-write-readPreference.json b/driver-core/src/test/resources/unified-test-format/crud/aggregate-write-readPreference.json index bc887e83cbc..c1fa3b4574a 100644 --- a/driver-core/src/test/resources/unified-test-format/crud/aggregate-write-readPreference.json +++ b/driver-core/src/test/resources/unified-test-format/crud/aggregate-write-readPreference.json @@ -78,11 +78,6 @@ "x": 33 } ] - }, - { - "collectionName": "coll1", - "databaseName": "db0", - "documents": [] } ], "tests": [ @@ -159,22 +154,6 @@ } ] } - ], - "outcome": [ - { - "collectionName": "coll1", - "databaseName": "db0", - "documents": [ - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ] - } ] }, { @@ -250,22 +229,6 @@ } ] } - ], - "outcome": [ - { - "collectionName": "coll1", - "databaseName": "db0", - "documents": [ - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ] - } ] }, { @@ -344,22 +307,6 @@ } ] } - ], - "outcome": [ - { - "collectionName": "coll1", - "databaseName": "db0", - "documents": [ - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ] - } ] }, { @@ -438,22 +385,6 @@ } ] } - ], - "outcome": [ - { - "collectionName": "coll1", - "databaseName": "db0", - "documents": [ - { - "_id": 2, - "x": 22 - }, - { - "_id": 3, - "x": 33 - } - ] - } ] } ] diff --git a/driver-core/src/test/resources/unified-test-format/crud/db-aggregate-write-readPreference.json b/driver-core/src/test/resources/unified-test-format/crud/db-aggregate-write-readPreference.json index 2a81282de81..b6460f001f2 100644 --- a/driver-core/src/test/resources/unified-test-format/crud/db-aggregate-write-readPreference.json +++ b/driver-core/src/test/resources/unified-test-format/crud/db-aggregate-write-readPreference.json @@ -52,13 +52,6 @@ } } ], - "initialData": [ - { - "collectionName": "coll0", - "databaseName": "db0", - "documents": [] - } - ], "tests": [ { "description": "Database-level aggregate with $out includes read preference for 5.0+ server", @@ -141,17 +134,6 @@ } ] } - ], - "outcome": [ - { - "collectionName": "coll0", - "databaseName": "db0", - "documents": [ - { - "_id": 1 - } - ] - } ] }, { @@ -235,17 +217,6 @@ } ] } - ], - "outcome": [ - { - "collectionName": "coll0", - "databaseName": "db0", - "documents": [ - { - "_id": 1 - } - ] - } ] }, { @@ -332,17 +303,6 @@ } ] } - ], - "outcome": [ - { - "collectionName": "coll0", - "databaseName": "db0", - "documents": [ - { - "_id": 1 - } - ] - } ] }, { @@ -429,17 +389,6 @@ } ] } - ], - "outcome": [ - { - "collectionName": "coll0", - "databaseName": "db0", - "documents": [ - { - "_id": 1 - } - ] - } ] } ] From 74a7583177d265441f342c18757979a29644dcba Mon Sep 17 00:00:00 2001 From: Nabil Hachicha Date: Wed, 17 Dec 2025 15:55:59 +0000 Subject: [PATCH 2/6] Fixes JAVA-6033 --- .../connection/DefaultServerMonitorTest.java | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/driver-core/src/test/unit/com/mongodb/internal/connection/DefaultServerMonitorTest.java b/driver-core/src/test/unit/com/mongodb/internal/connection/DefaultServerMonitorTest.java index 3aff244ea1e..c389c19ce0a 100644 --- a/driver-core/src/test/unit/com/mongodb/internal/connection/DefaultServerMonitorTest.java +++ b/driver-core/src/test/unit/com/mongodb/internal/connection/DefaultServerMonitorTest.java @@ -34,6 +34,7 @@ import org.bson.BsonDocument; import org.bson.ByteBufNIO; import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.opentest4j.AssertionFailedError; @@ -254,6 +255,66 @@ public void serverHeartbeatFailed(final ServerHeartbeatFailedEvent event) { assertEquals(expectedEvents, events); } + @Test + void shouldSendHeartbeatEventAfterInitialConnectionInPollMode() throws Exception { + // This test verifies that in POLL mode with a long heartbeat frequency, + // the monitor still fires a ServerHeartbeatSucceededEvent shortly after initial connection. + // This is critical for some unified tests like backpressure-network-error-fail.yml that rely on + // receiving an initial heartbeat event even with very long polling intervals. + + // Given + ConnectionDescription connectionDescription = createDefaultConnectionDescription(); + ServerDescription initialServerDescription = createDefaultServerDescription(); + String helloResponse = "{" + + LEGACY_HELLO_LOWER + ": true," + + "maxBsonObjectSize : 16777216, " + + "maxMessageSizeBytes : 48000000, " + + "maxWriteBatchSize : 1000, " + + "localTime : ISODate(\"2016-04-05T20:36:36.082Z\"), " + + "maxWireVersion : 4, " + + "minWireVersion : 0, " + + "ok : 1 " + + "}"; + + InternalConnection mockConnection = mock(InternalConnection.class); + when(mockConnection.getDescription()).thenReturn(connectionDescription); + when(mockConnection.getInitialServerDescription()).thenReturn(initialServerDescription); + when(mockConnection.getBuffer(anyInt())).thenReturn(new ByteBufNIO(ByteBuffer.allocate(1024))); + when(mockConnection.receive(any(), any())).thenReturn(BsonDocument.parse(helloResponse)); + + // When + TestServerMonitorListener listener = createTestServerMonitorListener(); + // Create monitor explicitly in POLL mode with long heartbeat frequency + DefaultServerMonitor monitor = new DefaultServerMonitor( + new ServerId(new ClusterId(), new ServerAddress()), + ServerSettings.builder() + .heartbeatFrequency(10000, TimeUnit.MILLISECONDS) + .serverMonitoringMode(com.mongodb.connection.ServerMonitoringMode.POLL) + .addServerMonitorListener(listener) + .build(), + createConnectionFactory(mockConnection), + ClusterConnectionMode.SINGLE, + null, + false, + SameObjectProvider.initialized(mock(SdamServerDescriptionManager.class)), + OPERATION_CONTEXT_FACTORY); + monitor.start(); + this.monitor = monitor; + + // Wait for heartbeat event - should happen quickly despite long heartbeatFrequency + listener.waitForEvents(ServerHeartbeatSucceededEvent.class, event -> true, 1, Duration.ofSeconds(2)); + ServerHeartbeatStartedEvent startedEvent = getEvent(ServerHeartbeatStartedEvent.class, listener); + ServerHeartbeatSucceededEvent succeededEvent = getEvent(ServerHeartbeatSucceededEvent.class, listener); + + // Then + assertEquals(connectionDescription.getConnectionId(), startedEvent.getConnectionId()); + assertEquals(connectionDescription.getConnectionId(), succeededEvent.getConnectionId()); + assertEquals(BsonDocument.parse(helloResponse), succeededEvent.getReply()); + assertTrue(succeededEvent.getElapsedTime(TimeUnit.NANOSECONDS) > 0); + // The event should not be awaited in POLL mode + Assertions.assertFalse(succeededEvent.isAwaited()); + } + private InternalConnectionFactory createConnectionFactory(final InternalConnection connection) { InternalConnectionFactory factory = mock(InternalConnectionFactory.class); From f099711bc19af9c96d94c1ba8422a5e087ad81b0 Mon Sep 17 00:00:00 2001 From: Nabil Hachicha Date: Wed, 17 Dec 2025 16:46:25 +0000 Subject: [PATCH 3/6] fix --- .../internal/connection/DefaultServerMonitor.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/driver-core/src/main/com/mongodb/internal/connection/DefaultServerMonitor.java b/driver-core/src/main/com/mongodb/internal/connection/DefaultServerMonitor.java index bb97517d315..032c9284dc8 100644 --- a/driver-core/src/main/com/mongodb/internal/connection/DefaultServerMonitor.java +++ b/driver-core/src/main/com/mongodb/internal/connection/DefaultServerMonitor.java @@ -216,6 +216,18 @@ public void run() { continue; } + // For POLL mode, if we just established initial connection, do an immediate heartbeat + boolean justConnected = previousServerDescription.getType() == UNKNOWN + && currentServerDescription.getType() != UNKNOWN + && !shouldStreamResponses + && connection != null && !connection.isClosed(); + + if (justConnected) { + // Do immediate heartbeat for newly connected server in POLL mode + // to fire the ServerHeartbeatSucceededEvent + continue; + } + logStateChange(previousServerDescription, currentServerDescription); sdamProvider.get().monitorUpdate(currentServerDescription); From e3e15d0a1b60e0f02ae51f79b4570bc6cab8f378 Mon Sep 17 00:00:00 2001 From: Nabil Hachicha Date: Thu, 18 Dec 2025 13:43:26 +0000 Subject: [PATCH 4/6] Update driver-core/src/main/com/mongodb/internal/connection/DefaultServerMonitor.java Co-authored-by: Ross Lawley --- .../connection/DefaultServerMonitor.java | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/driver-core/src/main/com/mongodb/internal/connection/DefaultServerMonitor.java b/driver-core/src/main/com/mongodb/internal/connection/DefaultServerMonitor.java index 032c9284dc8..63eaa6e5675 100644 --- a/driver-core/src/main/com/mongodb/internal/connection/DefaultServerMonitor.java +++ b/driver-core/src/main/com/mongodb/internal/connection/DefaultServerMonitor.java @@ -227,6 +227,34 @@ public void run() { // to fire the ServerHeartbeatSucceededEvent continue; } + boolean isPollMode = serverSettings.getServerMonitoringMode().equals(ServerMonitoringMode.POLL); + ServerDescription unknownConnectingServerDescription = unknownConnectingServerDescription(serverId, null); + ServerDescription currentServerDescription = unknownConnectingServerDescription; + try { + while (!isClosed) { + ServerDescription previousServerDescription = currentServerDescription; + currentServerDescription = lookupServerDescription(currentServerDescription); + boolean shouldStreamResponses = shouldStreamResponses(currentServerDescription); + if (shouldStreamResponses) { + ensureRoundTripTimeMonitorStarted(); + } + + if (isClosed) { + continue; + } + + if (currentCheckCancelled) { + waitForNext(); + currentCheckCancelled = false; + continue; + } + + // For POLL mode, if we just established initial connection, do an immediate heartbeat + if (isPollMode && connection != null && !connection.isClosed() + && previousServerDescription.equals(unknownConnectingServerDescription) + && currentServerDescription.equals(connection.getInitialServerDescription())) { + continue; + } logStateChange(previousServerDescription, currentServerDescription); sdamProvider.get().monitorUpdate(currentServerDescription); From 2e5d68433d9e02693ab26068d77d0c56c787111d Mon Sep 17 00:00:00 2001 From: Nabil Hachicha Date: Thu, 18 Dec 2025 14:12:20 +0000 Subject: [PATCH 5/6] fixing refactor --- .../connection/DefaultServerMonitor.java | 34 +------------------ 1 file changed, 1 insertion(+), 33 deletions(-) diff --git a/driver-core/src/main/com/mongodb/internal/connection/DefaultServerMonitor.java b/driver-core/src/main/com/mongodb/internal/connection/DefaultServerMonitor.java index 63eaa6e5675..565e26e7e22 100644 --- a/driver-core/src/main/com/mongodb/internal/connection/DefaultServerMonitor.java +++ b/driver-core/src/main/com/mongodb/internal/connection/DefaultServerMonitor.java @@ -196,38 +196,6 @@ public void close() { @Override public void run() { - ServerDescription currentServerDescription = unknownConnectingServerDescription(serverId, null); - try { - while (!isClosed) { - ServerDescription previousServerDescription = currentServerDescription; - currentServerDescription = lookupServerDescription(currentServerDescription); - boolean shouldStreamResponses = shouldStreamResponses(currentServerDescription); - if (shouldStreamResponses) { - ensureRoundTripTimeMonitorStarted(); - } - - if (isClosed) { - continue; - } - - if (currentCheckCancelled) { - waitForNext(); - currentCheckCancelled = false; - continue; - } - - // For POLL mode, if we just established initial connection, do an immediate heartbeat - boolean justConnected = previousServerDescription.getType() == UNKNOWN - && currentServerDescription.getType() != UNKNOWN - && !shouldStreamResponses - && connection != null && !connection.isClosed(); - - if (justConnected) { - // Do immediate heartbeat for newly connected server in POLL mode - // to fire the ServerHeartbeatSucceededEvent - continue; - } - boolean isPollMode = serverSettings.getServerMonitoringMode().equals(ServerMonitoringMode.POLL); ServerDescription unknownConnectingServerDescription = unknownConnectingServerDescription(serverId, null); ServerDescription currentServerDescription = unknownConnectingServerDescription; try { @@ -250,7 +218,7 @@ public void run() { } // For POLL mode, if we just established initial connection, do an immediate heartbeat - if (isPollMode && connection != null && !connection.isClosed() + if (!shouldStreamResponses && connection != null && !connection.isClosed() && previousServerDescription.equals(unknownConnectingServerDescription) && currentServerDescription.equals(connection.getInitialServerDescription())) { continue; From 2efac7893a08fc62243ca337772050bdfb89e2dc Mon Sep 17 00:00:00 2001 From: Nabil Hachicha Date: Thu, 18 Dec 2025 14:31:47 +0000 Subject: [PATCH 6/6] more simplification --- .../com/mongodb/internal/connection/DefaultServerMonitor.java | 1 - 1 file changed, 1 deletion(-) diff --git a/driver-core/src/main/com/mongodb/internal/connection/DefaultServerMonitor.java b/driver-core/src/main/com/mongodb/internal/connection/DefaultServerMonitor.java index 565e26e7e22..89ec44f6aa7 100644 --- a/driver-core/src/main/com/mongodb/internal/connection/DefaultServerMonitor.java +++ b/driver-core/src/main/com/mongodb/internal/connection/DefaultServerMonitor.java @@ -219,7 +219,6 @@ public void run() { // For POLL mode, if we just established initial connection, do an immediate heartbeat if (!shouldStreamResponses && connection != null && !connection.isClosed() - && previousServerDescription.equals(unknownConnectingServerDescription) && currentServerDescription.equals(connection.getInitialServerDescription())) { continue; }