def test_pool_paused_error_is_retryable(self): cmap_listener = CMAPListener() cmd_listener = OvertCommandListener() client = rs_or_single_client( maxPoolSize=1, event_listeners=[cmap_listener, cmd_listener]) self.addCleanup(client.close) for _ in range(10): cmap_listener.reset() cmd_listener.reset() threads = [InsertThread(client.pymongo_test.test) for _ in range(2)] fail_command = { 'mode': {'times': 1}, 'data': { 'failCommands': ['insert'], 'blockConnection': True, 'blockTimeMS': 1000, 'errorCode': 91, 'errorLabels': ['RetryableWriteError'], }, } with self.fail_point(fail_command): for thread in threads: thread.start() for thread in threads: thread.join() for thread in threads: self.assertTrue(thread.passed) # It's possible that SDAM can rediscover the server and mark the # pool ready before the thread in the wait queue has a chance # to run. Repeat the test until the thread actually encounters # a PoolClearedError. if cmap_listener.event_count(ConnectionCheckOutFailedEvent): break # Via CMAP monitoring, assert that the first check out succeeds. cmap_events = cmap_listener.events_by_type(( ConnectionCheckedOutEvent, ConnectionCheckOutFailedEvent, PoolClearedEvent)) msg = pprint.pformat(cmap_listener.events) self.assertIsInstance(cmap_events[0], ConnectionCheckedOutEvent, msg) self.assertIsInstance(cmap_events[1], PoolClearedEvent, msg) self.assertIsInstance( cmap_events[2], ConnectionCheckOutFailedEvent, msg) self.assertEqual(cmap_events[2].reason, ConnectionCheckOutFailedReason.CONN_ERROR, msg) self.assertIsInstance(cmap_events[3], ConnectionCheckedOutEvent, msg) # Connection check out failures are not reflected in command # monitoring because we only publish command events _after_ checking # out a connection. started = cmd_listener.results['started'] msg = pprint.pformat(cmd_listener.results) self.assertEqual(3, len(started), msg) succeeded = cmd_listener.results['succeeded'] self.assertEqual(2, len(succeeded), msg) failed = cmd_listener.results['failed'] self.assertEqual(1, len(failed), msg)
def test_close_leaves_pool_unpaused(self): # Needed until we implement PYTHON-2463. This test is related to # test_threads.TestThreads.test_client_disconnect listener = CMAPListener() client = single_client(event_listeners=[listener]) client.admin.command('ping') pool = get_pool(client) client.close() self.assertEqual(1, listener.event_count(PoolClearedEvent)) self.assertEqual(PoolState.READY, pool.state) # Checking out a connection should succeed with pool.get_socket({}): pass
def test_pool_paused_error_is_retryable(self): cmap_listener = CMAPListener() cmd_listener = OvertCommandListener() client = rs_or_single_client( maxPoolSize=1, heartbeatFrequencyMS=500, event_listeners=[cmap_listener, cmd_listener]) self.addCleanup(client.close) threads = [InsertThread(client.pymongo_test.test) for _ in range(3)] fail_command = { 'mode': { 'times': 1 }, 'data': { 'failCommands': ['insert'], 'blockConnection': True, 'blockTimeMS': 1000, 'errorCode': 91 }, } with self.fail_point(fail_command): for thread in threads: thread.start() for thread in threads: thread.join() for thread in threads: self.assertTrue(thread.passed) # The two threads in the wait queue fail the initial connection check # out attempt and then succeed on retry. self.assertEqual( 2, cmap_listener.event_count(ConnectionCheckOutFailedEvent)) # Connection check out failures are not reflected in command # monitoring because we only publish command events _after_ checking # out a connection. self.assertEqual(4, len(cmd_listener.results['started'])) self.assertEqual(3, len(cmd_listener.results['succeeded'])) self.assertEqual(1, len(cmd_listener.results['failed']))
def test_4_subscribe_to_events(self): listener = CMAPListener() client = single_client(event_listeners=[listener]) self.addCleanup(client.close) self.assertEqual(listener.event_count(PoolCreatedEvent), 1) # Creates a new connection. client.admin.command('isMaster') self.assertEqual(listener.event_count(ConnectionCheckOutStartedEvent), 1) self.assertEqual(listener.event_count(ConnectionCreatedEvent), 1) self.assertEqual(listener.event_count(ConnectionReadyEvent), 1) self.assertEqual(listener.event_count(ConnectionCheckedOutEvent), 1) self.assertEqual(listener.event_count(ConnectionCheckedInEvent), 1) # Uses the existing connection. client.admin.command('isMaster') self.assertEqual(listener.event_count(ConnectionCheckOutStartedEvent), 2) self.assertEqual(listener.event_count(ConnectionCheckedOutEvent), 2) self.assertEqual(listener.event_count(ConnectionCheckedInEvent), 2) client.close() self.assertEqual(listener.event_count(PoolClearedEvent), 1) self.assertEqual(listener.event_count(ConnectionClosedEvent), 1)