PYTHON-4960 More informative error message for stale primary (#2115)

This commit is contained in:
Shane Harvey 2025-03-05 10:30:52 -08:00 committed by GitHub
parent baf0344446
commit de09181b1c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 48 additions and 17 deletions

View File

@ -33,7 +33,7 @@ from typing import (
from bson.min_key import MinKey
from bson.objectid import ObjectId
from pymongo import common
from pymongo.errors import ConfigurationError
from pymongo.errors import ConfigurationError, PyMongoError
from pymongo.read_preferences import ReadPreference, _AggWritePref, _ServerMode
from pymongo.server_description import ServerDescription
from pymongo.server_selectors import Selection
@ -563,7 +563,11 @@ def _update_rs_from_primary(
if None not in new_election_tuple:
if None not in max_election_tuple and new_election_tuple < max_election_tuple:
# Stale primary, set to type Unknown.
sds[server_description.address] = server_description.to_unknown()
sds[server_description.address] = server_description.to_unknown(
PyMongoError(
f"primary marked stale due to electionId/setVersion mismatch, {new_election_tuple} is stale compared to {max_election_tuple}"
)
)
return _check_has_primary(sds), replica_set_name, max_set_version, max_election_id
max_election_id = server_description.election_id
@ -578,7 +582,11 @@ def _update_rs_from_primary(
max_election_safe = tuple(MinKey() if i is None else i for i in max_election_tuple)
if new_election_safe < max_election_safe:
# Stale primary, set to type Unknown.
sds[server_description.address] = server_description.to_unknown()
sds[server_description.address] = server_description.to_unknown(
PyMongoError(
f"primary marked stale due to electionId/setVersion mismatch, {new_election_tuple} is stale compared to {max_election_tuple}"
)
)
return _check_has_primary(sds), replica_set_name, max_set_version, max_election_id
else:
max_election_id = server_description.election_id
@ -591,7 +599,9 @@ def _update_rs_from_primary(
and server.address != server_description.address
):
# Reset old primary's type to Unknown.
sds[server.address] = server.to_unknown()
sds[server.address] = server.to_unknown(
PyMongoError("primary marked stale due to discovery of newer primary")
)
# There can be only one prior primary.
break

View File

@ -180,6 +180,9 @@ def check_outcome(self, topology, outcome):
server_type_name(expected_server_type),
server_type_name(actual_server_description.server_type),
)
expected_error = expected_server.get("error")
if expected_error:
self.assertIn(expected_error, str(actual_server_description.error))
self.assertEqual(expected_server.get("setName"), actual_server_description.replica_set_name)

View File

@ -58,7 +58,8 @@
"servers": {
"a:27017": {
"type": "Unknown",
"setName": null
"setName": null,
"error": "primary marked stale due to discovery of newer primary"
},
"b:27017": {
"type": "RSPrimary",

View File

@ -76,7 +76,8 @@
"a:27017": {
"type": "Unknown",
"setName": null,
"electionId": null
"electionId": null,
"error": "primary marked stale due to discovery of newer primary"
},
"b:27017": {
"type": "RSPrimary",
@ -123,7 +124,8 @@
"a:27017": {
"type": "Unknown",
"setName": null,
"electionId": null
"electionId": null,
"error": "primary marked stale due to electionId/setVersion mismatch"
},
"b:27017": {
"type": "RSPrimary",

View File

@ -76,7 +76,8 @@
"a:27017": {
"type": "Unknown",
"setName": null,
"electionId": null
"electionId": null,
"error": "primary marked stale due to discovery of newer primary"
},
"b:27017": {
"type": "RSPrimary",
@ -123,7 +124,8 @@
"a:27017": {
"type": "Unknown",
"setName": null,
"electionId": null
"electionId": null,
"error": "primary marked stale due to electionId/setVersion mismatch"
},
"b:27017": {
"type": "RSPrimary",

View File

@ -48,7 +48,8 @@
"a:27017": {
"type": "Unknown",
"setName": null,
"electionId": null
"electionId": null,
"error": "primary marked stale due to discovery of newer primary"
},
"b:27017": {
"type": "RSPrimary",
@ -124,6 +125,7 @@
"a:27017": {
"type": "Unknown",
"setName": null,
"error": "primary marked stale due to electionId/setVersion mismatch",
"electionId": null
},
"b:27017": {

View File

@ -48,7 +48,8 @@
"a:27017": {
"type": "Unknown",
"setName": null,
"electionId": null
"electionId": null,
"error": "primary marked stale due to discovery of newer primary"
},
"b:27017": {
"type": "RSPrimary",
@ -124,6 +125,7 @@
"a:27017": {
"type": "Unknown",
"setName": null,
"error": "primary marked stale due to electionId/setVersion mismatch",
"electionId": null
},
"b:27017": {

View File

@ -65,7 +65,8 @@
"a:27017": {
"type": "Unknown",
"setName": null,
"electionId": null
"electionId": null,
"error": "primary marked stale due to discovery of newer primary"
},
"b:27017": {
"type": "RSPrimary",

View File

@ -65,7 +65,8 @@
"a:27017": {
"type": "Unknown",
"setName": null,
"electionId": null
"electionId": null,
"error": "primary marked stale due to discovery of newer primary"
},
"b:27017": {
"type": "RSPrimary",

View File

@ -73,7 +73,8 @@
"a:27017": {
"type": "Unknown",
"setName": null,
"electionId": null
"electionId": null,
"error": "primary marked stale due to discovery of newer primary"
},
"b:27017": {
"type": "RSPrimary",
@ -117,7 +118,8 @@
"a:27017": {
"type": "Unknown",
"setName": null,
"electionId": null
"electionId": null,
"error": "primary marked stale due to electionId/setVersion mismatch"
},
"b:27017": {
"type": "RSPrimary",

View File

@ -81,7 +81,8 @@
"b:27017": {
"type": "Unknown",
"setName": null,
"electionId": null
"electionId": null,
"error": "primary marked stale due to electionId/setVersion mismatch"
}
},
"topologyType": "ReplicaSetWithPrimary",
@ -128,7 +129,8 @@
"b:27017": {
"type": "Unknown",
"setName": null,
"electionId": null
"electionId": null,
"error": "primary marked stale due to electionId/setVersion mismatch"
}
},
"topologyType": "ReplicaSetWithPrimary",

View File

@ -180,6 +180,9 @@ def check_outcome(self, topology, outcome):
server_type_name(expected_server_type),
server_type_name(actual_server_description.server_type),
)
expected_error = expected_server.get("error")
if expected_error:
self.assertIn(expected_error, str(actual_server_description.error))
self.assertEqual(expected_server.get("setName"), actual_server_description.replica_set_name)