@@ -513,6 +513,67 @@ async def test_connection_timeout_message(self):
513513 str (error .exception ),
514514 )
515515
516+ @async_client_context .require_failCommand_appName
517+ async def test_pool_backoff_preserves_existing_collections (self ):
518+ client = await self .async_rs_or_single_client ()
519+ coll = self .db .t
520+ pool = await async_get_pool (client )
521+ await coll .insert_many ([{"x" : 1 } for _ in range (10 )])
522+ t = SocketGetter (self .c , pool )
523+ await t .start ()
524+ while t .state != "connection" :
525+ await asyncio .sleep (0.1 )
526+
527+ assert not t .sock .conn_closed ()
528+
529+ # Mock a session establishment overload.
530+ mock_connection_fail = {
531+ "configureFailPoint" : "failCommand" ,
532+ "mode" : {"times" : 1 },
533+ "data" : {
534+ "closeConnection" : True ,
535+ },
536+ }
537+
538+ async with self .fail_point (mock_connection_fail ):
539+ await coll .find_one ({})
540+
541+ # Make sure the pool is out of backoff state.
542+ assert pool ._backoff == 0
543+
544+ # Make sure the existing socket was not affected.
545+ assert not t .sock .conn_closed ()
546+
547+ # Cleanup
548+ await t .release_conn ()
549+ await t .join ()
550+ await pool .close ()
551+
552+ async def test_pool_check_backoff (self ):
553+ # Test that Pool recovers from two connection failures in a row.
554+ # This exercises code at the end of Pool._check().
555+ cx_pool = await self .create_pool (max_pool_size = 1 , connect_timeout = 1 , wait_queue_timeout = 1 )
556+ self .addAsyncCleanup (cx_pool .close )
557+
558+ async with cx_pool .checkout () as conn :
559+ # Simulate a closed socket without telling the Connection it's
560+ # closed.
561+ await conn .conn .close ()
562+
563+ # Enable backoff.
564+ cx_pool ._backoff = 1
565+
566+ # Swap pool's address with a bad one.
567+ address , cx_pool .address = cx_pool .address , ("foo.com" , 1234 )
568+ with self .assertRaises (AutoReconnect ):
569+ async with cx_pool .checkout ():
570+ pass
571+
572+ # Back to normal, semaphore was correctly released.
573+ cx_pool .address = address
574+ async with cx_pool .checkout ():
575+ pass
576+
516577
517578class TestPoolMaxSize (_TestPoolingBase ):
518579 async def test_max_pool_size (self ):
0 commit comments