Skip to content

Commit 0793138

Browse files
authored
PYTHON-4117 Require 4.3.1+ server version when using failCommand errorLabels option (mongodb#1526)
1 parent 5b5a7e6 commit 0793138

38 files changed

+6620
-6094
lines changed

pymongo/helpers.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,8 @@ def _get_wce_doc(result: Mapping[str, Any]) -> Optional[Mapping[str, Any]]:
254254
# convenient to attach it to the writeConcernError doc itself.
255255
error_labels = result.get("errorLabels")
256256
if error_labels:
257+
# Copy to avoid changing the original document.
258+
wce = wce.copy()
257259
wce["errorLabels"] = error_labels
258260
return wce
259261

pymongo/mongo_client.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@
8383
PyMongoError,
8484
ServerSelectionTimeoutError,
8585
WaitQueueTimeoutError,
86+
WriteConcernError,
8687
)
8788
from pymongo.lock import _HAS_REGISTER_AT_FORK, _create_lock, _release_locks
8889
from pymongo.monitoring import ConnectionClosedReason
@@ -2175,7 +2176,7 @@ def _retryable_error_doc(exc: PyMongoError) -> Optional[Mapping[str, Any]]:
21752176
return None
21762177

21772178

2178-
def _add_retryable_write_error(exc: PyMongoError, max_wire_version: int) -> None:
2179+
def _add_retryable_write_error(exc: PyMongoError, max_wire_version: int, is_mongos: bool) -> None:
21792180
doc = _retryable_error_doc(exc)
21802181
if doc:
21812182
code = doc.get("code", 0)
@@ -2192,7 +2193,10 @@ def _add_retryable_write_error(exc: PyMongoError, max_wire_version: int) -> None
21922193
for label in doc.get("errorLabels", []):
21932194
exc._add_error_label(label)
21942195
else:
2195-
if code in helpers._RETRYABLE_ERROR_CODES:
2196+
# Do not consult writeConcernError for pre-4.4 mongos.
2197+
if isinstance(exc, WriteConcernError) and is_mongos:
2198+
pass
2199+
elif code in helpers._RETRYABLE_ERROR_CODES:
21962200
exc._add_error_label("RetryableWriteError")
21972201

21982202
# Connection errors are always retryable except NotPrimaryError and WaitQueueTimeoutError which is
@@ -2432,6 +2436,7 @@ def _write(self) -> T:
24322436
"""
24332437
try:
24342438
max_wire_version = 0
2439+
is_mongos = False
24352440
self._server = self._get_server()
24362441
with self._client._checkout(self._server, self._session) as conn:
24372442
max_wire_version = conn.max_wire_version
@@ -2440,6 +2445,7 @@ def _write(self) -> T:
24402445
and self._server.description.retryable_writes_supported
24412446
and conn.supports_sessions
24422447
)
2448+
is_mongos = conn.is_mongos
24432449
if not sessions_supported:
24442450
# A retry is not possible because this server does
24452451
# not support sessions raise the last error.
@@ -2450,7 +2456,7 @@ def _write(self) -> T:
24502456
if not self._retryable:
24512457
raise
24522458
# Add the RetryableWriteError label, if applicable.
2453-
_add_retryable_write_error(exc, max_wire_version)
2459+
_add_retryable_write_error(exc, max_wire_version, is_mongos)
24542460
raise
24552461

24562462
def _read(self) -> T:

test/command_monitoring/writeConcernError.json

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"schemaVersion": "1.4",
44
"runOnRequirements": [
55
{
6-
"minServerVersion": "4.1.0",
6+
"minServerVersion": "4.3.1",
77
"topologies": [
88
"replicaset"
99
],
@@ -66,11 +66,11 @@
6666
"failCommands": [
6767
"insert"
6868
],
69+
"errorLabels": [
70+
"RetryableWriteError"
71+
],
6972
"writeConcernError": {
70-
"code": 91,
71-
"errorLabels": [
72-
"RetryableWriteError"
73-
]
73+
"code": 91
7474
}
7575
}
7676
}
@@ -112,11 +112,11 @@
112112
"reply": {
113113
"ok": 1,
114114
"n": 1,
115+
"errorLabels": [
116+
"RetryableWriteError"
117+
],
115118
"writeConcernError": {
116-
"code": 91,
117-
"errorLabels": [
118-
"RetryableWriteError"
119-
]
119+
"code": 91
120120
}
121121
},
122122
"commandName": "insert"
@@ -152,4 +152,4 @@
152152
]
153153
}
154154
]
155-
}
155+
}

0 commit comments

Comments
 (0)