Mongo Shell

mongo "mongodb+srv://admatic-cluster-7qyyr.mongodb.net/test" --username admatic
MongoDB shell version v4.0.6
Enter password:
Implicit session: session { "id" : UUID("60f1c2ab-2e30-4ff0-9b73-12a03b503d1d") }
MongoDB server version: 4.0.6
MongoDB Enterprise Admatic-Cluster-shard-0:PRIMARY>

Create the collections

use hr

db.createCollection("employees")
db.createCollection("events")

db.employees.insert({ employee: 3, status: "Active" })
WriteResult({ "nInserted" : 1 })

Retry Transaction

// Runs the txnFunc and retries if TransientTransactionError encountered
function runTransactionWithRetry(txnFunc, session) {
    while (true) {
        try {
            txnFunc(session);  // performs transaction
            break;
        } catch (error) {
            print("Transaction aborted. Caught exception during transaction.");

            // If transient error, retry the whole transaction
            if ( error.hasOwnProperty("errorLabels") && error.errorLabels.includes( "TransientTransactionError")  ) {
                print("TransientTransactionError, retrying transaction ...");
                continue;
            } else {
                throw error;
            }
        }
    }
}

Retry Commit Operation

// Retries commit if UnknownTransactionCommitResult encountered
function commitWithRetry(session) {
    while (true) {
        try {
            session.commitTransaction(); // Uses write concern set at transaction start.
            print("Transaction committed.");
            break;
        } catch (error) {
            // Can retry commit
            if (error.hasOwnProperty("errorLabels") && error.errorLabels.includes( "UnknownTransactionCommitResult") ) {
                print("UnknownTransactionCommitResult, retrying commit operation ...");
                continue;
            } else {
                print("Error during commit ...");
                throw error;
            }
       }
    }
}

Updates two collections in a transactions

function updateEmployeeInfo(session) {
    employeesCollection = session.getDatabase("hr").employees;
    eventsCollection = session.getDatabase("hr").events;

    session.startTransaction( { readConcern: { level: "snapshot" }, writeConcern: { w: "majority" } } );

    try{
        employeesCollection.updateOne( { employee: 3 }, { $set: { status: "Inactive" } } );
        eventsCollection.insertOne( { employee: 3, status: { new: "Inactive", old: "Active" } } );
    } catch (error) {
        print("Caught exception during transaction, aborting.");
        session.abortTransaction();
        throw error;
    }

    commitWithRetry(session);
}

Start a session

session = db.getMongo().startSession( { readPreference: { mode: "primary" } } );
session { "id" : UUID("0f41cae7-562b-40d2-880d-f19b623e7dcb") }

Run Transaction With Retry

try{
   runTransactionWithRetry(updateEmployeeInfo, session);
} catch (error) {
   // Do something with error
} finally {
   session.endSession();
}
Transaction committed.

Verify

db.employees.find()
{ "_id" : ObjectId("5c77965c155eb2e753a00752"), "employee" : 3, "status" : "Inactive" }
db.events.find()
{ "_id" : ObjectId("5c77966f155eb2e753a00753"), "employee" : 3, "status" : { "new" : "Inactive", "old" : "Active" } }

results matching ""

    No results matching ""