From 20d5a9cf814d3a22310d162b67762569e231d772 Mon Sep 17 00:00:00 2001 From: Shane Harvey Date: Mon, 1 Mar 2021 14:09:27 -0800 Subject: [PATCH] PYTHON-2543 Do not mark a server unknown from a "writeErrors" response (#570) --- pymongo/topology.py | 6 +- .../errors/write_errors_ignored.json | 96 +++++++++++++++++++ test/test_discovery_and_monitoring.py | 4 +- 3 files changed, 104 insertions(+), 2 deletions(-) create mode 100644 test/discovery_and_monitoring/errors/write_errors_ignored.json diff --git a/pymongo/topology.py b/pymongo/topology.py index 194884a75..4e07db86b 100644 --- a/pymongo/topology.py +++ b/pymongo/topology.py @@ -32,7 +32,8 @@ from pymongo.errors import (ConnectionFailure, NotMasterError, OperationFailure, PyMongoError, - ServerSelectionTimeoutError) + ServerSelectionTimeoutError, + WriteError) from pymongo.monitor import SrvMonitor from pymongo.pool import PoolOptions from pymongo.server import Server @@ -578,6 +579,9 @@ class Topology(object): # operation fails because of any network error besides a socket # timeout...." return + elif issubclass(exc_type, WriteError): + # Ignore writeErrors. + return elif issubclass(exc_type, NotMasterError): # As per the SDAM spec if: # - the server sees a "not master" error, and diff --git a/test/discovery_and_monitoring/errors/write_errors_ignored.json b/test/discovery_and_monitoring/errors/write_errors_ignored.json new file mode 100644 index 000000000..6b80673c1 --- /dev/null +++ b/test/discovery_and_monitoring/errors/write_errors_ignored.json @@ -0,0 +1,96 @@ +{ + "description": "writeErrors field is ignored", + "uri": "mongodb://a/?replicaSet=rs", + "phases": [ + { + "description": "Primary A is discovered", + "responses": [ + [ + "a:27017", + { + "ok": 1, + "ismaster": true, + "hosts": [ + "a:27017" + ], + "setName": "rs", + "minWireVersion": 0, + "maxWireVersion": 9, + "topologyVersion": { + "processId": { + "$oid": "000000000000000000000001" + }, + "counter": { + "$numberLong": "1" + } + } + } + ] + ], + "outcome": { + "servers": { + "a:27017": { + "type": "RSPrimary", + "setName": "rs", + "topologyVersion": { + "processId": { + "$oid": "000000000000000000000001" + }, + "counter": { + "$numberLong": "1" + } + }, + "pool": { + "generation": 0 + } + } + }, + "topologyType": "ReplicaSetWithPrimary", + "logicalSessionTimeoutMinutes": null, + "setName": "rs" + } + }, + { + "description": "Ignore command error with writeErrors field", + "applicationErrors": [ + { + "address": "a:27017", + "when": "afterHandshakeCompletes", + "maxWireVersion": 9, + "type": "command", + "response": { + "ok": 1, + "writeErrors": [ + { + "errmsg": "NotMasterNoSlaveOk", + "code": 13435 + } + ] + } + } + ], + "outcome": { + "servers": { + "a:27017": { + "type": "RSPrimary", + "setName": "rs", + "topologyVersion": { + "processId": { + "$oid": "000000000000000000000001" + }, + "counter": { + "$numberLong": "1" + } + }, + "pool": { + "generation": 0 + } + } + }, + "topologyType": "ReplicaSetWithPrimary", + "logicalSessionTimeoutMinutes": null, + "setName": "rs" + } + } + ] +} diff --git a/test/test_discovery_and_monitoring.py b/test/test_discovery_and_monitoring.py index ddb87271a..4ffffffae 100644 --- a/test/test_discovery_and_monitoring.py +++ b/test/test_discovery_and_monitoring.py @@ -29,7 +29,8 @@ from pymongo.errors import (AutoReconnect, NetworkTimeout, NotMasterError, OperationFailure) -from pymongo.helpers import _check_command_response +from pymongo.helpers import (_check_command_response, + _check_write_command_response) from pymongo.ismaster import IsMaster from pymongo.server_description import ServerDescription, SERVER_TYPE from pymongo.settings import TopologySettings @@ -94,6 +95,7 @@ def got_app_error(topology, app_error): try: if error_type == 'command': _check_command_response(app_error['response'], max_wire_version) + _check_write_command_response(app_error['response']) elif error_type == 'network': raise AutoReconnect('mock non-timeout network error') elif error_type == 'timeout':