Skip to content

Instantly share code, notes, and snippets.

@GoodnessEzeokafor
Created November 29, 2021 12:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save GoodnessEzeokafor/29f0cac84c6b1f32c0c7f053388e0762 to your computer and use it in GitHub Desktop.
Save GoodnessEzeokafor/29f0cac84c6b1f32c0c7f053388e0762 to your computer and use it in GitHub Desktop.
Mongo-Db-Transactions
/**
* Rules for MONGODB Multi Document Transactions
* All data modeling rules still applies
* Transactions should be the most common operation
* Pass in the session to all statements
* Implement retry logic , transactions can always abort
* Plan for DDL operations
*/
import db, { ClientSession } from 'mongoose';
/**
* Source: https://docs.mongodb.com/manual/reference/method/Session.commitTransaction/
*/
const databaseHelper = {
runTransactionWithRetry: async (txnFunc: any, session: ClientSession) => {
let retries = 0
while (retries < 3) {
try {
console.log("-------- runTransactionWithRetry function ----------")
await txnFunc(session); // performs transaction
await session.commitTransaction(); // Uses write concern set at transaction start.
console.log("-------- runTransactionWithRetry function ----------")
console.log("Transaction commited.............")
// commit transaction
break;
} catch (error: any) {
// If transient error, retry the whole transaction
console.log("----------------error during commit ------------------")
console.log(error)
console.log("----------------error during commit ------------------")
console.log(error.errorLabels)
if (error.hasOwnProperty("errorLabels") && error.errorLabels.includes("TransientTransactionError")) {
console.log("TransientTransactionError, retrying transaction ...");
retries++
continue;
} else if (error.hasOwnProperty("errorLabels") && error.errorLabels.includes("UnknownTransactionCommitResult")) {
console.log("UnknownTransactionCommitResult, retrying commit operation ...");
retries++
continue;
} else {
await session.abortTransaction();
return Promise.reject(error);
}
}
}
},
commitWithRetry: async (session: ClientSession) => {
while (true) {
try {
session.commitTransaction(); // Uses write concern set at transaction start.
console.log("Transaction committed.");
break;
} catch (error: any) {
// Can retry commit
if (error.hasOwnProperty("errorLabels") && error.errorLabels.includes("UnknownTransactionCommitResult")) {
console.log("UnknownTransactionCommitResult, retrying commit operation ...");
continue;
} else {
console.log("Error during commit ...");
throw error;
}
}
}
},
executeTransaction: async (transactionProcess: any) => {
const session = await db.startSession();
session.startTransaction();
try {
await databaseHelper.runTransactionWithRetry(transactionProcess, session);
} catch (error: any) {
return Promise.reject(error) ;
} finally {
await session.endSession();
}
}
}
export default databaseHelper
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment