Skip to content

Commit b6dd34d

Browse files
committed
PYTHON-5505 Add test that even non-retryable write ops will be retried on overload
The server only adds the "Retryable" error label when it knows it is safe to retry.
1 parent c2ff971 commit b6dd34d

File tree

2 files changed

+44
-2
lines changed

2 files changed

+44
-2
lines changed

test/asynchronous/test_backpressure.py

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
"configureFailPoint": "failCommand",
3232
"mode": {"times": 1},
3333
"data": {
34-
"failCommands": ["find", "insert"],
34+
"failCommands": ["find", "insert", "update"],
3535
"errorCode": 462, # IngressRequestRateLimitExceeded
3636
"errorLabels": ["Retryable"],
3737
},
@@ -98,6 +98,27 @@ async def test_retry_overload_error_insert_one(self):
9898

9999
self.assertIn("Retryable", str(error.exception))
100100

101+
@async_client_context.require_failCommand_appName
102+
async def test_retry_overload_error_update_many(self):
103+
# Even though update_many is not a retryable write operation, it will
104+
# still be retried via the "Retryable" error label.
105+
await self.db.t.insert_one({"x": 1})
106+
107+
# Ensure command is retried on overload error.
108+
fail_once = mock_overload_error.copy()
109+
fail_once["mode"] = {"times": _MAX_RETRIES}
110+
async with self.fail_point(fail_once):
111+
await self.db.t.update_many({}, {"$set": {"x": 2}})
112+
113+
# Ensure command stops retrying after _MAX_RETRIES.
114+
fail_many_times = mock_overload_error.copy()
115+
fail_many_times["mode"] = {"times": _MAX_RETRIES + 1}
116+
async with self.fail_point(fail_many_times):
117+
with self.assertRaises(PyMongoError) as error:
118+
await self.db.t.update_many({}, {"$set": {"x": 2}})
119+
120+
self.assertIn("Retryable", str(error.exception))
121+
101122
@async_client_context.require_failCommand_appName
102123
async def test_retry_overload_error_getMore(self):
103124
coll = self.db.t

test/test_backpressure.py

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
"configureFailPoint": "failCommand",
3232
"mode": {"times": 1},
3333
"data": {
34-
"failCommands": ["find", "insert"],
34+
"failCommands": ["find", "insert", "update"],
3535
"errorCode": 462, # IngressRequestRateLimitExceeded
3636
"errorLabels": ["Retryable"],
3737
},
@@ -98,6 +98,27 @@ def test_retry_overload_error_insert_one(self):
9898

9999
self.assertIn("Retryable", str(error.exception))
100100

101+
@client_context.require_failCommand_appName
102+
def test_retry_overload_error_update_many(self):
103+
# Even though update_many is not a retryable write operation, it will
104+
# still be retried via the "Retryable" error label.
105+
self.db.t.insert_one({"x": 1})
106+
107+
# Ensure command is retried on overload error.
108+
fail_once = mock_overload_error.copy()
109+
fail_once["mode"] = {"times": _MAX_RETRIES}
110+
with self.fail_point(fail_once):
111+
self.db.t.update_many({}, {"$set": {"x": 2}})
112+
113+
# Ensure command stops retrying after _MAX_RETRIES.
114+
fail_many_times = mock_overload_error.copy()
115+
fail_many_times["mode"] = {"times": _MAX_RETRIES + 1}
116+
with self.fail_point(fail_many_times):
117+
with self.assertRaises(PyMongoError) as error:
118+
self.db.t.update_many({}, {"$set": {"x": 2}})
119+
120+
self.assertIn("Retryable", str(error.exception))
121+
101122
@client_context.require_failCommand_appName
102123
def test_retry_overload_error_getMore(self):
103124
coll = self.db.t

0 commit comments

Comments
 (0)