The YAML and JSON files in this directory are platform-independent tests meant to exercise a driver's implementation of the Convenient API for Transactions spec. These tests utilize the Unified Test Format.
Several prose tests, which are not easily expressed in YAML, are also presented in this file. Those tests will need to be manually implemented by each driver.
Write a callback that raises a custom exception or error that does not include either UnknownTransactionCommitResult or
TransientTransactionError error labels. Execute this callback using withTransaction and assert that the callback's
error bypasses any retry logic within withTransaction and is propagated to the caller of withTransaction.
Write a callback that returns a custom value (e.g. boolean, string, object). Execute this callback using
withTransaction and assert that the callback's return value is propagated to the caller of withTransaction.
Drivers should test that withTransaction enforces a non-configurable timeout before retrying both commits and entire
transactions. Specifically, three cases should be checked:
- If the callback raises an error with the TransientTransactionError label and the retry timeout has been exceeded,
withTransactionshould propagate the error to its caller. - If committing raises an error with the UnknownTransactionCommitResult label, and the retry timeout has been exceeded,
withTransactionshould propagate the error to its caller. - If committing raises an error with the TransientTransactionError label and the retry timeout has been exceeded,
withTransactionshould propagate the error to its caller. This case may occur if the commit was internally retried against a new primary after a failover and the second primary returned a NoSuchTransaction error response.
If possible, drivers should implement these tests without requiring the test runner to block for the full duration of
the retry timeout. This might be done by internally modifying the timeout value used by withTransaction with some
private API or using a mock timer.
Drivers should test that retries within withTransaction do not occur immediately.
- let
clientbe aMongoClient - let
collbe a collection - Now, run transactions without backoff:
-
Configure the random number generator used for jitter to always return
0-- this effectively disables backoff. -
Configure a fail point that forces 13 retries like so:
set_fail_point( { "configureFailPoint": "failCommand", "mode": { "times": 13 }, # sufficiently high enough such that the time effect of backoff is noticeable "data": { "failCommands": ["commitTransaction"], "errorCode": 251, }, } )
Note: errorCode 251 is NoSuchTransaction.
-
Define the callback for the transaction as follows:
def callback(session): coll.insert_one({}, session=session)
-
Let
no_backoff_timebe the duration of the withTransaction API call:start = time.monotonic() with client.start_session() as s: s.with_transaction(callback) end = time.monotonic() no_backoff_time = end - start
-
- Now run the command with backoff:
- Configure the random number generator used for jitter to always return
1. - Configure a fail point that forces 13 retries like in step 3.2.
- Use the same callback defined in 3.3.
- Let
with_backoff_timebe the duration of the withTransaction API call:start = time.monotonic() with client.start_session() as s: s.with_transaction(callback) end = time.monotonic() no_backoff_time = end - start
- Configure the random number generator used for jitter to always return
- Compare the durations of the two runs.
The sum of 13 backoffs is roughly 1.8 seconds. There is a half-second window to account for potential variance between the two runs.
assertTrue(absolute_value(with_backoff_time - (no_backoff_time + 1.8 seconds)) < 0.5 seconds)
- 2026-01-07: Fixed Retry Backoff is Enforced test accordingly to the updated spec.
- 2025-11-18: Added Backoff test.
- 2024-09-06: Migrated from reStructuredText to Markdown.
- 2024-02-08: Converted legacy tests to unified format.
- 2021-04-29: Remove text about write concern timeouts from prose test.