jstests/concurrency/fsm_workload_helpers/auto_retry_transaction.js
/**
     * Runs 'func' inside of a transaction started with 'txnOptions', and automatically retries
     * until it either succeeds or the server returns a non-TransientTransactionError error
     * response. If retryOnKilledSession is true, the transaction will be automatically retried on
     * error codes that may come from a killed session as well. There is a probability of
     * 'prepareProbability' that the transaction is prepared before committing.
     *
     * The caller should take care to ensure 'func' doesn't modify any captured variables in a
     * speculative fashion where calling it multiple times would lead to unintended behavior. The
     * transaction started by the withTxnAndAutoRetry() function is only known to have committed
     * after the withTxnAndAutoRetry() function returns.
     */
Runs 'func' inside of a transaction started with 'txnOptions', and automatically retries
until it either succeeds or the server returns a non-TransientTransactionError error
response. If retryOnKilledSession is true, the transaction will be automatically retried on
error codes that may come from a killed session as well. There is a probability of
'prepareProbability' that the transaction is prepared before committing.

The caller should take care to ensure 'func' doesn't modify any captured variables in a
speculative fashion where calling it multiple times would lead to unintended behavior. The
transaction started by the withTxnAndAutoRetry() function is only known to have committed
after the withTxnAndAutoRetry() function returns.
Runs ' func ' inside of a transaction started with ' txnOptions ' and automatically retries until it either succeeds or the server returns a non - TransientTransactionError error response . If retryOnKilledSession is true the transaction will be automatically retried on error codes that may come from a killed session as well . There is a probability of ' prepareProbability ' that the transaction is prepared before committing . The caller should take care to ensure ' func ' doesn ' t modify any captured variables in a speculative fashion where calling it multiple times would lead to unintended behavior . The transaction started by the withTxnAndAutoRetry () function is only known to have committed after the withTxnAndAutoRetry () function returns .
function withTxnAndAutoRetry(session, func, {
        txnOptions: txnOptions = {
            readConcern: {level: TestData.defaultTransactionReadConcernLevel || 'snapshot'},
            writeConcern: TestData.hasOwnProperty("defaultTransactionWriteConcernW")
                ? {w: TestData.defaultTransactionWriteConcernW, wtimeout: kDefaultWtimeout}
                : undefined
        },
        retryOnKilledSession: retryOnKilledSession = false,
        prepareProbability: prepareProbability = 0.0
    } = {}) {
        assert(!retryOnKilledSession || prepareProbability === 0.0,
               "retrying on killed session error codes isn't supported with prepareProbability");
        let hasTransientError;
        let iterations = 0;
        do {
            session.startTransaction_forTesting(txnOptions, {ignoreActiveTxn: true});
            let hasCommitTxnError = false;
            hasTransientError = false;
            iterations += 1;
            if (iterations % 10 === 0) {
                print("withTxnAndAutoRetry has iterated " + iterations + " times.");
            }
            try {
                func();
                try {
                    const rand = Random.rand();
                    if (rand < prepareProbability) {
                        const prepareTimestamp = PrepareHelpers.prepareTransaction(session);
                        PrepareHelpers.commitTransaction(session, prepareTimestamp);
                    } else {
                        commitTransactionWithRetries(session, retryOnKilledSession);
                    }
                } catch (e) {
                    hasCommitTxnError = true;
                    throw e;
                }
            } catch (e) {
                if (!hasCommitTxnError) {
                    assert.commandWorkedOrFailedWithCode(
                        session.abortTransaction_forTesting(),
                        [ErrorCodes.NoSuchTransaction, ErrorCodes.Interrupted]);
                }
                if (shouldRetryEntireTxnOnError(e, hasCommitTxnError, retryOnKilledSession)) {
                    print("Retrying transaction due to transient error: " + tojson(e));
                    hasTransientError = true;
                    continue;
                }
                throw e;
            }
        } while (hasTransientError);
    }
function withTxnAndAutoRetry ( session , func , { txnOptions : txnOptions = { readConcern : { level : TestData . defaultTransactionReadConcernLevel || 'snapshot' } , writeConcern : TestData . hasOwnProperty ( "defaultTransactionWriteConcernW" ) ? { w : TestData . defaultTransactionWriteConcernW , wtimeout : kDefaultWtimeout } : undefined } , retryOnKilledSession : retryOnKilledSession = false , prepareProbability : prepareProbability = 0.0 } = { } ) { assert ( ! retryOnKilledSession || prepareProbability === 0.0 , "retrying on killed session error codes isn't supported with prepareProbability" ) ; let hasTransientError ; let iterations = 0 ; do { session . startTransaction_forTesting ( txnOptions , { ignoreActiveTxn : true } ) ; let hasCommitTxnError = false ; hasTransientError = false ; iterations += 1 ; if ( iterations % 10 === 0 ) { print ( "withTxnAndAutoRetry has iterated " + iterations + " times." ) ; } try { func ( ) ; try { const rand = Random . rand ( ) ; if ( rand < prepareProbability ) { const prepareTimestamp = PrepareHelpers . prepareTransaction ( session ) ; PrepareHelpers . commitTransaction ( session , prepareTimestamp ) ; } else { commitTransactionWithRetries ( session , retryOnKilledSession ) ; } } catch ( e ) { hasCommitTxnError = true ; throw e ; } } catch ( e ) { if ( ! hasCommitTxnError ) { assert . commandWorkedOrFailedWithCode ( session . abortTransaction_forTesting ( ) , [ ErrorCodes . NoSuchTransaction , ErrorCodes . Interrupted ] ) ; } if ( shouldRetryEntireTxnOnError ( e , hasCommitTxnError , retryOnKilledSession ) ) { print ( "Retrying transaction due to transient error: " + tojson ( e ) ) ; hasTransientError = true ; continue ; } throw e ; } } while ( hasTransientError ) ; }
Runs 'func' inside of a transaction started with 'txnOptions', and automatically retries
 until it either succeeds or the server returns a non-TransientTransactionError error
 response.
Runs ' func ' inside of a transaction started with ' txnOptions ' and automatically retries until it either succeeds or the server returns a non - TransientTransactionError error response .
// Committing a manually prepared transaction isn't currently supported when sessions might // be killed. // We need to call abortTransaction_forTesting() in order to update the mongo // shell's state such that it agrees no transaction is currently in progress on // this session. // The transaction may have implicitly been aborted by the server or killed by // the kill_session helper and will therefore return a // NoSuchTransaction/Interrupted error code.