From dc73514cbaa9766c46f9ac717285fb08080587d1 Mon Sep 17 00:00:00 2001 From: "mongodb-drivers-pr-bot[bot]" <147046816+mongodb-drivers-pr-bot[bot]@users.noreply.github.com> Date: Wed, 12 Mar 2025 12:21:42 -0700 Subject: [PATCH] PYTHON-5202 WaitQueueTimeoutError should not clear the pool (#2192) [v4.11] (#2196) Co-authored-by: Shane Harvey --- pymongo/asynchronous/topology.py | 3 +++ pymongo/synchronous/topology.py | 3 +++ test/asynchronous/test_client.py | 13 +++++++++++-- test/test_client.py | 13 +++++++++++-- 4 files changed, 28 insertions(+), 4 deletions(-) diff --git a/pymongo/asynchronous/topology.py b/pymongo/asynchronous/topology.py index 07671c9a7..bee26dca7 100644 --- a/pymongo/asynchronous/topology.py +++ b/pymongo/asynchronous/topology.py @@ -40,6 +40,7 @@ from pymongo.errors import ( OperationFailure, PyMongoError, ServerSelectionTimeoutError, + WaitQueueTimeoutError, WriteError, ) from pymongo.hello import Hello @@ -877,6 +878,8 @@ class Topology: # Clear the pool. await server.reset(service_id) elif isinstance(error, ConnectionFailure): + if isinstance(error, WaitQueueTimeoutError): + return # "Client MUST replace the server's description with type Unknown # ... MUST NOT request an immediate check of the server." if not self._settings.load_balanced: diff --git a/pymongo/synchronous/topology.py b/pymongo/synchronous/topology.py index 861712f02..d13b8c57d 100644 --- a/pymongo/synchronous/topology.py +++ b/pymongo/synchronous/topology.py @@ -36,6 +36,7 @@ from pymongo.errors import ( OperationFailure, PyMongoError, ServerSelectionTimeoutError, + WaitQueueTimeoutError, WriteError, ) from pymongo.hello import Hello @@ -875,6 +876,8 @@ class Topology: # Clear the pool. server.reset(service_id) elif isinstance(error, ConnectionFailure): + if isinstance(error, WaitQueueTimeoutError): + return # "Client MUST replace the server's description with type Unknown # ... MUST NOT request an immediate check of the server." if not self._settings.load_balanced: diff --git a/test/asynchronous/test_client.py b/test/asynchronous/test_client.py index 744a170be..bbad6f491 100644 --- a/test/asynchronous/test_client.py +++ b/test/asynchronous/test_client.py @@ -111,6 +111,7 @@ from pymongo.errors import ( NetworkTimeout, OperationFailure, ServerSelectionTimeoutError, + WaitQueueTimeoutError, WriteConcernError, ) from pymongo.monitoring import ServerHeartbeatListener, ServerHeartbeatStartedEvent @@ -1311,8 +1312,16 @@ class TestClient(AsyncIntegrationTest): self.assertAlmostEqual(30, client.options.server_selection_timeout) async def test_waitQueueTimeoutMS(self): - client = await self.async_rs_or_single_client(waitQueueTimeoutMS=2000) - self.assertEqual((await async_get_pool(client)).opts.wait_queue_timeout, 2) + listener = CMAPListener() + client = await self.async_rs_or_single_client( + waitQueueTimeoutMS=10, maxPoolSize=1, event_listeners=[listener] + ) + pool = await async_get_pool(client) + self.assertEqual(pool.opts.wait_queue_timeout, 0.01) + async with pool.checkout(): + with self.assertRaises(WaitQueueTimeoutError): + await client.test.command("ping") + self.assertFalse(listener.events_by_type(monitoring.PoolClearedEvent)) async def test_socketKeepAlive(self): pool = await async_get_pool(self.client) diff --git a/test/test_client.py b/test/test_client.py index 2a33077f5..dd0b1b591 100644 --- a/test/test_client.py +++ b/test/test_client.py @@ -100,6 +100,7 @@ from pymongo.errors import ( NetworkTimeout, OperationFailure, ServerSelectionTimeoutError, + WaitQueueTimeoutError, WriteConcernError, ) from pymongo.monitoring import ServerHeartbeatListener, ServerHeartbeatStartedEvent @@ -1270,8 +1271,16 @@ class TestClient(IntegrationTest): self.assertAlmostEqual(30, client.options.server_selection_timeout) def test_waitQueueTimeoutMS(self): - client = self.rs_or_single_client(waitQueueTimeoutMS=2000) - self.assertEqual((get_pool(client)).opts.wait_queue_timeout, 2) + listener = CMAPListener() + client = self.rs_or_single_client( + waitQueueTimeoutMS=10, maxPoolSize=1, event_listeners=[listener] + ) + pool = get_pool(client) + self.assertEqual(pool.opts.wait_queue_timeout, 0.01) + with pool.checkout(): + with self.assertRaises(WaitQueueTimeoutError): + client.test.command("ping") + self.assertFalse(listener.events_by_type(monitoring.PoolClearedEvent)) def test_socketKeepAlive(self): pool = get_pool(self.client)