Skip to content

Commit 52d7795

Browse files
committed
PYTHON-2970 Prioritize electionId over setVersion for stale primary check (#845)
(cherry picked from commit 225d131)
1 parent 57fea8b commit 52d7795

12 files changed

+511
-52
lines changed

doc/changelog.rst

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,48 @@
11
Changelog
22
=========
33

4+
Changes in Version 3.13.0
5+
-------------------------
6+
7+
Issues Resolved
8+
...............
9+
10+
PyMongo 3.13 drops support for Python 3.4.
11+
12+
Bug fixes
13+
.........
14+
15+
- Fixed a bug where the client could be unable to discover the new primary
16+
after a simultaneous replica set election and reconfig (`PYTHON-2970`_).
17+
18+
Deprecations
19+
............
20+
21+
- Deprecated :meth:`~pymongo.collection.Collection.map_reduce` and
22+
:meth:`~pymongo.collection.Collection.inline_map_reduce`.
23+
Use :meth:`~pymongo.collection.Collection.aggregate` instead.
24+
25+
See the `PyMongo 3.13.0 release notes in JIRA`_ for the list of resolved issues
26+
in this release.
27+
28+
.. _PYTHON-2970: https://jira.mongodb.org/browse/PYTHON-2970
29+
.. _PyMongo 3.13.0 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=31570
30+
31+
Changes in Version 3.12.3
32+
-------------------------
33+
34+
Issues Resolved
35+
...............
36+
37+
Version 3.12.3 fixes a bug that prevented :meth:`bson.json_util.loads` from
38+
decoding a document with a non-string "$regex" field (`PYTHON-3028`_).
39+
40+
See the `PyMongo 3.12.3 release notes in JIRA`_ for the list of resolved issues
41+
in this release.
42+
43+
.. _PYTHON-3028: https://jira.mongodb.org/browse/PYTHON-3028
44+
.. _PyMongo 3.12.3 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=32505
45+
446
Changes in Version 3.12.2
547
-------------------------
648

pymongo/collection.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3170,19 +3170,20 @@ def inline_map_reduce(self, map, reduce, full_response=False, session=None, **kw
31703170
helper method, e.g.::
31713171
31723172
>>> db.test.inline_map_reduce(map, reduce, limit=2)
3173+
31733174
.. versionchanged:: 3.13
31743175
Support for this function is deprecated in
31753176
MongoDB 4.0, and is removed in PyMongo 4.0. Migrate to
31763177
:meth:`aggregate`. For more guidance on this migration see:
31773178
31783179
- https://docs.mongodb.com/manual/reference/map-reduce-to-aggregation-pipeline/
31793180
- https://docs.mongodb.com/manual/reference/aggregation-commands-comparison/
3180-
3181-
.. _mapReduce command: https://docs.mongodb.com/manual/reference/command/mapReduce/
31823181
.. versionchanged:: 3.6
31833182
Added ``session`` parameter.
31843183
.. versionchanged:: 3.4
31853184
Added the `collation` option.
3185+
3186+
.. _mapReduce command: https://docs.mongodb.com/manual/reference/command/mapReduce/
31863187
"""
31873188
warnings.warn(
31883189
'inline_map_reduce is deprecated, use aggregate instead',

pymongo/topology_description.py

Lines changed: 11 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
from collections import namedtuple
1818

19+
from bson.min_key import MinKey
1920
from pymongo import common
2021
from pymongo.errors import ConfigurationError
2122
from pymongo.read_preferences import ReadPreference
@@ -493,24 +494,16 @@ def _update_rs_from_primary(
493494
sds.pop(server_description.address)
494495
return (_check_has_primary(sds), replica_set_name, max_set_version, max_election_id)
495496

496-
max_election_tuple = max_set_version, max_election_id
497-
if None not in server_description.election_tuple:
498-
if (
499-
None not in max_election_tuple
500-
and max_election_tuple > server_description.election_tuple
501-
):
502-
503-
# Stale primary, set to type Unknown.
504-
sds[server_description.address] = server_description.to_unknown()
505-
return (_check_has_primary(sds), replica_set_name, max_set_version, max_election_id)
506-
507-
max_election_id = server_description.election_id
508-
509-
if server_description.set_version is not None and (
510-
max_set_version is None or server_description.set_version > max_set_version
511-
):
512-
513-
max_set_version = server_description.set_version
497+
new_election_tuple = server_description.election_id, server_description.set_version
498+
max_election_tuple = max_election_id, max_set_version
499+
new_election_safe = tuple(MinKey() if i is None else i for i in new_election_tuple)
500+
max_election_safe = tuple(MinKey() if i is None else i for i in max_election_tuple)
501+
if new_election_safe >= max_election_safe:
502+
max_election_id, max_set_version = new_election_tuple
503+
else:
504+
# Stale primary, set to type Unknown.
505+
sds[server_description.address] = server_description.to_unknown()
506+
return _check_has_primary(sds), replica_set_name, max_set_version, max_election_id
514507

515508
# We've heard from the primary. Is it the same primary as before?
516509
for server in sds.values():
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
{
2+
"description": "ElectionId is considered higher precedence than setVersion",
3+
"uri": "mongodb://a/?replicaSet=rs",
4+
"phases": [
5+
{
6+
"responses": [
7+
[
8+
"a:27017",
9+
{
10+
"ok": 1,
11+
"helloOk": true,
12+
"isWritablePrimary": true,
13+
"hosts": [
14+
"a:27017",
15+
"b:27017"
16+
],
17+
"setName": "rs",
18+
"setVersion": 1,
19+
"electionId": {
20+
"$oid": "000000000000000000000001"
21+
},
22+
"minWireVersion": 0,
23+
"maxWireVersion": 6
24+
}
25+
],
26+
[
27+
"b:27017",
28+
{
29+
"ok": 1,
30+
"helloOk": true,
31+
"isWritablePrimary": true,
32+
"hosts": [
33+
"a:27017",
34+
"b:27017"
35+
],
36+
"setName": "rs",
37+
"setVersion": 2,
38+
"electionId": {
39+
"$oid": "000000000000000000000001"
40+
},
41+
"minWireVersion": 0,
42+
"maxWireVersion": 6
43+
}
44+
],
45+
[
46+
"a:27017",
47+
{
48+
"ok": 1,
49+
"helloOk": true,
50+
"isWritablePrimary": true,
51+
"hosts": [
52+
"a:27017",
53+
"b:27017"
54+
],
55+
"setName": "rs",
56+
"setVersion": 1,
57+
"electionId": {
58+
"$oid": "000000000000000000000002"
59+
},
60+
"minWireVersion": 0,
61+
"maxWireVersion": 6
62+
}
63+
]
64+
],
65+
"outcome": {
66+
"servers": {
67+
"a:27017": {
68+
"type": "RSPrimary",
69+
"setName": "rs",
70+
"setVersion": 1,
71+
"electionId": {
72+
"$oid": "000000000000000000000002"
73+
}
74+
},
75+
"b:27017": {
76+
"type": "Unknown",
77+
"setName": null,
78+
"setVersion": null,
79+
"electionId": null
80+
}
81+
},
82+
"topologyType": "ReplicaSetWithPrimary",
83+
"logicalSessionTimeoutMinutes": null,
84+
"setName": "rs",
85+
"maxSetVersion": 1,
86+
"maxElectionId": {
87+
"$oid": "000000000000000000000002"
88+
}
89+
}
90+
}
91+
]
92+
}

test/discovery_and_monitoring/rs/null_election_id.json

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -120,16 +120,19 @@
120120
"outcome": {
121121
"servers": {
122122
"a:27017": {
123-
"type": "RSPrimary",
124-
"setName": "rs",
125-
"setVersion": 1,
126-
"electionId": null
127-
},
128-
"b:27017": {
129123
"type": "Unknown",
130124
"setName": null,
125+
"setVersion": null,
131126
"electionId": null
132127
},
128+
"b:27017": {
129+
"type": "RSPrimary",
130+
"setName": "rs",
131+
"setVersion": 1,
132+
"electionId": {
133+
"$oid": "000000000000000000000002"
134+
}
135+
},
133136
"c:27017": {
134137
"type": "Unknown",
135138
"setName": null,
@@ -170,16 +173,19 @@
170173
"outcome": {
171174
"servers": {
172175
"a:27017": {
173-
"type": "RSPrimary",
174-
"setName": "rs",
175-
"setVersion": 1,
176-
"electionId": null
177-
},
178-
"b:27017": {
179176
"type": "Unknown",
180177
"setName": null,
178+
"setVersion": null,
181179
"electionId": null
182180
},
181+
"b:27017": {
182+
"type": "RSPrimary",
183+
"setName": "rs",
184+
"setVersion": 1,
185+
"electionId": {
186+
"$oid": "000000000000000000000002"
187+
}
188+
},
183189
"c:27017": {
184190
"type": "Unknown",
185191
"setName": null,

test/discovery_and_monitoring/rs/secondary_ignore_ok_0.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"description": "New primary",
2+
"description": "Secondary ignored when ok is zero",
33
"uri": "mongodb://a,b/?replicaSet=rs",
44
"phases": [
55
{

0 commit comments

Comments
 (0)