|
19 | 19 | import pathlib |
20 | 20 | import sys |
21 | 21 | from time import perf_counter |
| 22 | +from unittest import mock |
22 | 23 | from unittest.mock import patch |
23 | 24 |
|
24 | 25 | from pymongo.common import MAX_ADAPTIVE_RETRIES |
@@ -228,7 +229,7 @@ async def test_01_operation_retry_uses_exponential_backoff(self, random_func): |
228 | 229 | self.assertTrue(abs((end1 - start1) - (end0 - start0 + 0.3)) < 0.3) |
229 | 230 |
|
230 | 231 | @async_client_context.require_failCommand_appName |
231 | | - async def test_03_overload_retries_limited(self): |
| 232 | + async def test_02_overload_retries_limited(self): |
232 | 233 | # Drivers should test that overload errors are retried a maximum of two times. |
233 | 234 |
|
234 | 235 | # 1. Let `client` be a `MongoClient`. |
@@ -260,7 +261,7 @@ async def test_03_overload_retries_limited(self): |
260 | 261 | self.assertEqual(len(self.listener.started_events), MAX_ADAPTIVE_RETRIES + 1) |
261 | 262 |
|
262 | 263 | @async_client_context.require_failCommand_appName |
263 | | - async def test_04_overload_retries_limited_configured(self): |
| 264 | + async def test_03_overload_retries_limited_configured(self): |
264 | 265 | # Drivers should test that overload errors are retried a maximum of maxAdaptiveRetries times. |
265 | 266 | max_retries = 1 |
266 | 267 |
|
@@ -294,6 +295,40 @@ async def test_04_overload_retries_limited_configured(self): |
294 | 295 | # 6. Assert that the total number of started commands is max_retries + 1. |
295 | 296 | self.assertEqual(len(self.listener.started_events), max_retries + 1) |
296 | 297 |
|
| 298 | + @async_client_context.require_failCommand_fail_point |
| 299 | + async def test_04_backoff_is_not_applied_for_non_overload_errors(self): |
| 300 | + # Drivers should test that backoff is not applied for non-overload retryable errors. |
| 301 | + if _IS_SYNC: |
| 302 | + mock_target = "pymongo.synchronous.helpers._RetryPolicy.backoff" |
| 303 | + else: |
| 304 | + mock_target = "pymongo.asynchronous.helpers._RetryPolicy.backoff" |
| 305 | + |
| 306 | + # 1. Let `client` be a `MongoClient`. |
| 307 | + client = self.client |
| 308 | + |
| 309 | + # 2. Let `coll` be a collection. |
| 310 | + coll = client.test.test |
| 311 | + await coll.insert_one({}) |
| 312 | + |
| 313 | + # 3. Configure a failpoint with a retryable error that is NOT an overload error. |
| 314 | + failpoint = { |
| 315 | + "configureFailPoint": "failCommand", |
| 316 | + "mode": {"times": 1}, |
| 317 | + "data": { |
| 318 | + "failCommands": ["find"], |
| 319 | + "errorCode": 91, # ShutdownInProgress |
| 320 | + "errorLabels": ["RetryableError"], |
| 321 | + }, |
| 322 | + } |
| 323 | + |
| 324 | + # 4. Perform a find operation with `coll` that succeeds on its first retry attempt. |
| 325 | + with mock.patch(mock_target, return_value=1) as mock_backoff: |
| 326 | + async with self.fail_point(failpoint): |
| 327 | + await coll.find_one({}) |
| 328 | + |
| 329 | + # 5. Assert that no backoff was used for the retry attempt. |
| 330 | + mock_backoff.assert_not_called() |
| 331 | + |
297 | 332 |
|
298 | 333 | # Location of JSON test specifications. |
299 | 334 | if _IS_SYNC: |
|
0 commit comments