PYTHON-2082 Unpin session after RetryableWriteErrors from commitTransaction (#451)
PYTHON-2154 PYTHON-2189 Remove 4.5 transaction test workarounds
This commit is contained in:
parent
26913ea8e1
commit
4457714d1b
@ -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(
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user