@@ -1421,12 +1421,15 @@ def is_retrying():
14211421 # be a persistent outage. Attempting to retry in this case will
14221422 # most likely be a waste of time.
14231423 raise
1424- except Exception as exc :
1424+ except PyMongoError as exc :
14251425 if not retryable :
14261426 raise
1427- # Add the RetryableWriteError label.
1428- if (not _retryable_writes_error (exc , max_wire_version )
1429- or is_retrying ()):
1427+ # Add the RetryableWriteError label, if applicable.
1428+ _add_retryable_write_error (exc , max_wire_version )
1429+ retryable_error = exc .has_error_label ("RetryableWriteError" )
1430+ if retryable_error :
1431+ session ._unpin_mongos ()
1432+ if is_retrying () or not retryable_error :
14301433 raise
14311434 if bulk :
14321435 bulk .retrying = True
@@ -2170,7 +2173,7 @@ def _retryable_error_doc(exc):
21702173 return None
21712174
21722175
2173- def _retryable_writes_error (exc , max_wire_version ):
2176+ def _add_retryable_write_error (exc , max_wire_version ):
21742177 doc = _retryable_error_doc (exc )
21752178 if doc :
21762179 code = doc .get ('code' , 0 )
@@ -2183,18 +2186,18 @@ def _retryable_writes_error(exc, max_wire_version):
21832186 "to your connection string." )
21842187 raise OperationFailure (errmsg , code , exc .details )
21852188 if max_wire_version >= 9 :
2186- # MongoDB 4.4+ utilizes RetryableWriteError.
2187- return 'RetryableWriteError' in doc .get ('errorLabels' , [])
2189+ # In MongoDB 4.4+, the server reports the error labels.
2190+ for label in doc .get ('errorLabels' , []):
2191+ exc ._add_error_label (label )
21882192 else :
21892193 if code in helpers ._RETRYABLE_ERROR_CODES :
21902194 exc ._add_error_label ("RetryableWriteError" )
2191- return True
2192- return False
21932195
2194- if isinstance (exc , ConnectionFailure ):
2196+ # Connection errors are always retryable except NotMasterError which is
2197+ # handled above.
2198+ if (isinstance (exc , ConnectionFailure ) and
2199+ not isinstance (exc , NotMasterError )):
21952200 exc ._add_error_label ("RetryableWriteError" )
2196- return True
2197- return False
21982201
21992202
22002203class _MongoClientErrorHandler (object ):
@@ -2232,7 +2235,8 @@ def __exit__(self, exc_type, exc_val, exc_tb):
22322235 self .session ._server_session .mark_dirty ()
22332236
22342237 if issubclass (exc_type , PyMongoError ):
2235- if exc_val .has_error_label ("TransientTransactionError" ):
2238+ if (exc_val .has_error_label ("TransientTransactionError" ) or
2239+ exc_val .has_error_label ("RetryableWriteError" )):
22362240 self .session ._unpin_mongos ()
22372241
22382242 err_ctx = _ErrorContext (
0 commit comments