diff --git a/pymongo/topology.py b/pymongo/topology.py index 194884a752..4e07db86b5 100644 --- a/pymongo/topology.py +++ b/pymongo/topology.py @@ -32,7 +32,8 @@ 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 @@ def _handle_error(self, address, err_ctx): # 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 0000000000..6b80673c12 --- /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 ddb87271a9..4ffffffaea 100644 --- a/test/test_discovery_and_monitoring.py +++ b/test/test_discovery_and_monitoring.py @@ -29,7 +29,8 @@ 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':