diff --git a/test/asynchronous/test_client_backpressure.py b/test/asynchronous/test_client_backpressure.py index 12084d999..bf139105d 100644 --- a/test/asynchronous/test_client_backpressure.py +++ b/test/asynchronous/test_client_backpressure.py @@ -278,18 +278,54 @@ class AsyncTestClientBackpressure(AsyncIntegrationTest): self.assertTrue(abs((end1 - start1) - (end0 - start0 + 3.1)) < 1) @async_client_context.require_failCommand_appName - async def test_02_overload_retries_limited(self): + async def test_03_overload_retries_limited(self): # Drivers should test that without adaptive retries enabled, overload errors are retried a maximum of five times. # 1. Let `client` be a `MongoClient`. client = self.client + # 2. Let `coll` be a collection. + coll = client.pymongo_test.coll + + # 3. Configure the following failpoint: + failpoint = { + "configureFailPoint": "failCommand", + "mode": "alwaysOn", + "data": { + "failCommands": ["find"], + "errorCode": 462, # IngressRequestRateLimitExceeded + "errorLabels": ["RetryableError", "SystemOverloadedError"], + }, + } + + # 4. Perform a find operation with `coll` that fails. + async with self.fail_point(failpoint): + with self.assertRaises(PyMongoError) as error: + await coll.find_one({}) + + # 5. Assert that the raised error contains both the `RetryableError` and `SystemOverLoadedError` error labels. + self.assertIn("RetryableError", str(error.exception)) + self.assertIn("SystemOverloadedError", str(error.exception)) + + # 6. Assert that the total number of started commands is MAX_RETRIES + 1. + self.assertEqual(len(self.listener.started_events), _MAX_RETRIES + 1) + + @async_client_context.require_failCommand_appName + async def test_03_adaptive_retries_limited_by_tokens(self): + # Drivers should test that when enabled, adaptive retries are limited by the number of tokens in the bucket. + + # 1. Let `client` be a `MongoClient` with adaptiveRetries=True. + client = await self.async_rs_or_single_client( + adaptive_retries=True, event_listeners=[self.listener] + ) + # 2. Set `client`'s retry token bucket to have 2 tokens. + client._retry_policy.token_bucket.tokens = 2 # 3. Let `coll` be a collection. coll = client.pymongo_test.coll # 4. Configure the following failpoint: failpoint = { "configureFailPoint": "failCommand", - "mode": "alwaysOn", + "mode": {"times": 3}, "data": { "failCommands": ["find"], "errorCode": 462, # IngressRequestRateLimitExceeded @@ -306,39 +342,8 @@ class AsyncTestClientBackpressure(AsyncIntegrationTest): self.assertIn("RetryableError", str(error.exception)) self.assertIn("SystemOverloadedError", str(error.exception)) - # 7. Assert that the total number of started commands is MAX_RETRIES + 1. - self.assertEqual(len(self.listener.started_events), _MAX_RETRIES + 1) - - @async_client_context.require_failCommand_appName - async def test_03_adaptive_retries_limited_by_tokens(self): - # Drivers should test that when enabled, adaptive retries are limited by the number of tokens in the bucket. - - # 1. Let `client` be a `MongoClient` with adaptiveRetries=True. - client = await self.async_rs_or_single_client(adaptive_retries=True) - # 2. Set `client`'s retry token bucket to have 1 token. - client._retry_policy.token_bucket.tokens = 1 - # 3. Let `coll` be a collection. - coll = client.pymongo_test.coll - - # 4. Configure the following failpoint: - failpoint = { - "configureFailPoint": "failCommand", - "mode": {"times": 2}, - "data": { - "failCommands": ["find", "insert", "update"], - "errorCode": 462, # IngressRequestRateLimitExceeded - "errorLabels": ["RetryableError", "SystemOverloadedError"], - }, - } - - # 5. Perform a find operation with `coll` that fails. - async with self.fail_point(failpoint): - with self.assertRaises(PyMongoError) as error: - await coll.find_one({}) - - # 6. Assert that the raised error contains both the `RetryableError` and `SystemOverLoadedError` error labels. - self.assertIn("RetryableError", str(error.exception)) - self.assertIn("SystemOverloadedError", str(error.exception)) + # 7. Assert that the total number of started commands is 3: one for the initial attempt and two for the retries. + self.assertEqual(len(self.listener.started_events), 3) # Location of JSON test specifications. diff --git a/test/test_client_backpressure.py b/test/test_client_backpressure.py index 347a5cd08..2219b4f4b 100644 --- a/test/test_client_backpressure.py +++ b/test/test_client_backpressure.py @@ -278,18 +278,52 @@ class TestClientBackpressure(IntegrationTest): self.assertTrue(abs((end1 - start1) - (end0 - start0 + 3.1)) < 1) @client_context.require_failCommand_appName - def test_02_overload_retries_limited(self): + def test_03_overload_retries_limited(self): # Drivers should test that without adaptive retries enabled, overload errors are retried a maximum of five times. # 1. Let `client` be a `MongoClient`. client = self.client + # 2. Let `coll` be a collection. + coll = client.pymongo_test.coll + + # 3. Configure the following failpoint: + failpoint = { + "configureFailPoint": "failCommand", + "mode": "alwaysOn", + "data": { + "failCommands": ["find"], + "errorCode": 462, # IngressRequestRateLimitExceeded + "errorLabels": ["RetryableError", "SystemOverloadedError"], + }, + } + + # 4. Perform a find operation with `coll` that fails. + with self.fail_point(failpoint): + with self.assertRaises(PyMongoError) as error: + coll.find_one({}) + + # 5. Assert that the raised error contains both the `RetryableError` and `SystemOverLoadedError` error labels. + self.assertIn("RetryableError", str(error.exception)) + self.assertIn("SystemOverloadedError", str(error.exception)) + + # 6. Assert that the total number of started commands is MAX_RETRIES + 1. + self.assertEqual(len(self.listener.started_events), _MAX_RETRIES + 1) + + @client_context.require_failCommand_appName + def test_03_adaptive_retries_limited_by_tokens(self): + # Drivers should test that when enabled, adaptive retries are limited by the number of tokens in the bucket. + + # 1. Let `client` be a `MongoClient` with adaptiveRetries=True. + client = self.rs_or_single_client(adaptive_retries=True, event_listeners=[self.listener]) + # 2. Set `client`'s retry token bucket to have 2 tokens. + client._retry_policy.token_bucket.tokens = 2 # 3. Let `coll` be a collection. coll = client.pymongo_test.coll # 4. Configure the following failpoint: failpoint = { "configureFailPoint": "failCommand", - "mode": "alwaysOn", + "mode": {"times": 3}, "data": { "failCommands": ["find"], "errorCode": 462, # IngressRequestRateLimitExceeded @@ -306,39 +340,8 @@ class TestClientBackpressure(IntegrationTest): self.assertIn("RetryableError", str(error.exception)) self.assertIn("SystemOverloadedError", str(error.exception)) - # 7. Assert that the total number of started commands is MAX_RETRIES + 1. - self.assertEqual(len(self.listener.started_events), _MAX_RETRIES + 1) - - @client_context.require_failCommand_appName - def test_03_adaptive_retries_limited_by_tokens(self): - # Drivers should test that when enabled, adaptive retries are limited by the number of tokens in the bucket. - - # 1. Let `client` be a `MongoClient` with adaptiveRetries=True. - client = self.rs_or_single_client(adaptive_retries=True) - # 2. Set `client`'s retry token bucket to have 1 token. - client._retry_policy.token_bucket.tokens = 1 - # 3. Let `coll` be a collection. - coll = client.pymongo_test.coll - - # 4. Configure the following failpoint: - failpoint = { - "configureFailPoint": "failCommand", - "mode": {"times": 2}, - "data": { - "failCommands": ["find", "insert", "update"], - "errorCode": 462, # IngressRequestRateLimitExceeded - "errorLabels": ["RetryableError", "SystemOverloadedError"], - }, - } - - # 5. Perform a find operation with `coll` that fails. - with self.fail_point(failpoint): - with self.assertRaises(PyMongoError) as error: - coll.find_one({}) - - # 6. Assert that the raised error contains both the `RetryableError` and `SystemOverLoadedError` error labels. - self.assertIn("RetryableError", str(error.exception)) - self.assertIn("SystemOverloadedError", str(error.exception)) + # 7. Assert that the total number of started commands is 3: one for the initial attempt and two for the retries. + self.assertEqual(len(self.listener.started_events), 3) # Location of JSON test specifications.