PYTHON-2082 Unpin session after RetryableWriteErrors from commitTransaction (#451)

PYTHON-2154 PYTHON-2189 Remove 4.5 transaction test workarounds
This commit is contained in:
Shane Harvey 2020-07-01 18:32:58 -07:00 committed by GitHub
parent 26913ea8e1
commit 4457714d1b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 18 additions and 21 deletions

View File

@ -1421,12 +1421,15 @@ class MongoClient(common.BaseObject):
# be a persistent outage. Attempting to retry in this case will
# most likely be a waste of time.
raise
except Exception as exc:
except PyMongoError as exc:
if not retryable:
raise
# Add the RetryableWriteError label.
if (not _retryable_writes_error(exc, max_wire_version)
or is_retrying()):
# Add the RetryableWriteError label, if applicable.
_add_retryable_write_error(exc, max_wire_version)
retryable_error = exc.has_error_label("RetryableWriteError")
if retryable_error:
session._unpin_mongos()
if is_retrying() or not retryable_error:
raise
if bulk:
bulk.retrying = True
@ -2170,7 +2173,7 @@ def _retryable_error_doc(exc):
return None
def _retryable_writes_error(exc, max_wire_version):
def _add_retryable_write_error(exc, max_wire_version):
doc = _retryable_error_doc(exc)
if doc:
code = doc.get('code', 0)
@ -2183,18 +2186,18 @@ def _retryable_writes_error(exc, max_wire_version):
"to your connection string.")
raise OperationFailure(errmsg, code, exc.details)
if max_wire_version >= 9:
# MongoDB 4.4+ utilizes RetryableWriteError.
return 'RetryableWriteError' in doc.get('errorLabels', [])
# In MongoDB 4.4+, the server reports the error labels.
for label in doc.get('errorLabels', []):
exc._add_error_label(label)
else:
if code in helpers._RETRYABLE_ERROR_CODES:
exc._add_error_label("RetryableWriteError")
return True
return False
if isinstance(exc, ConnectionFailure):
# Connection errors are always retryable except NotMasterError which is
# handled above.
if (isinstance(exc, ConnectionFailure) and
not isinstance(exc, NotMasterError)):
exc._add_error_label("RetryableWriteError")
return True
return False
class _MongoClientErrorHandler(object):
@ -2232,7 +2235,8 @@ class _MongoClientErrorHandler(object):
self.session._server_session.mark_dirty()
if issubclass(exc_type, PyMongoError):
if exc_val.has_error_label("TransientTransactionError"):
if (exc_val.has_error_label("TransientTransactionError") or
exc_val.has_error_label("RetryableWriteError")):
self.session._unpin_mongos()
err_ctx = _ErrorContext(

View File

@ -842,7 +842,6 @@ class TestSampleShellCommands(IntegrationTest):
class TestTransactionExamples(IntegrationTest):
@client_context.require_version_max(4, 4, 99) # PYTHON-2154 skip on 4.5+
@client_context.require_transactions
def test_transactions(self):
# Transaction examples

View File

@ -415,13 +415,7 @@ def create_test(scenario_def, test, name):
@client_context.require_test_commands
@client_context.require_transactions
def run_scenario(self):
try:
self.run_scenario(scenario_def, test)
except OperationFailure as exc:
if (client_context.version.at_least(4, 5) and
client_context.is_mongos and exc.code == 13388):
self.skipTest('PYTHON-2189 Ignoring StaleConfig error: %r' % (
exc.details))
self.run_scenario(scenario_def, test)
return run_scenario