diff --git a/pymongo/asynchronous/topology.py b/pymongo/asynchronous/topology.py index 76f0fb6cde..f00f62ffe5 100644 --- a/pymongo/asynchronous/topology.py +++ b/pymongo/asynchronous/topology.py @@ -41,6 +41,7 @@ OperationFailure, PyMongoError, ServerSelectionTimeoutError, + WaitQueueTimeoutError, WriteError, ) from pymongo.hello import Hello @@ -892,6 +893,8 @@ async def _handle_error(self, address: _Address, err_ctx: _ErrorContext) -> None # 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 ea0edae919..0af793a969 100644 --- a/pymongo/synchronous/topology.py +++ b/pymongo/synchronous/topology.py @@ -37,6 +37,7 @@ OperationFailure, PyMongoError, ServerSelectionTimeoutError, + WaitQueueTimeoutError, WriteError, ) from pymongo.hello import Hello @@ -890,6 +891,8 @@ def _handle_error(self, address: _Address, err_ctx: _ErrorContext) -> None: # 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 acc815c8a4..6da3620fb5 100644 --- a/test/asynchronous/test_client.py +++ b/test/asynchronous/test_client.py @@ -111,6 +111,7 @@ NetworkTimeout, OperationFailure, ServerSelectionTimeoutError, + WaitQueueTimeoutError, WriteConcernError, ) from pymongo.monitoring import ServerHeartbeatListener, ServerHeartbeatStartedEvent @@ -1311,8 +1312,16 @@ async def test_server_selection_timeout(self): 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 8e99866cc8..cb7e1639f7 100644 --- a/test/test_client.py +++ b/test/test_client.py @@ -100,6 +100,7 @@ NetworkTimeout, OperationFailure, ServerSelectionTimeoutError, + WaitQueueTimeoutError, WriteConcernError, ) from pymongo.monitoring import ServerHeartbeatListener, ServerHeartbeatStartedEvent @@ -1270,8 +1271,16 @@ def test_server_selection_timeout(self): 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)