I was looking at some patterns on how to use MongoDB Transactions but I want it to be a common wrapper and should be simple enough for nodejs beginners (like me) to understand. I saw some functions accepting another, function with multiple parameters, as a parameter, but you need to take care of overloading
cases.
Thinking of a simple solution, why not just wrap all arguments into a single variable like a map
. This may not work for others but certainly works on our case.
First, I need to make sure that I only have 1 DB Connection always. Hence I created a Singleton
class.
const mongoose = require('mongoose');
...
...
// Define Singleton DB Connection Class
class Connection {
constructor() {
if (!Connection.instance) {
mongoose.connect(config.mongoose.url, config.mongoose.options);
this.conn = mongoose.connection;
this.conn.on('error', () => logger.error.bind(console, 'connection error'));
this.conn.on('open', () => logger.info(`Connected to MongoDB ${config.mongoose.url} for Transaction...`));
}
}
}
module.exports = new Connection();
I will use this class in every part of my systems and it will ensure that I won't be having multiple cases of DB connection.
Now to create a transaction wrapper, I do this. This is a self-managed transaction meaning I dont need to call commit and rollback. But if you want to manually handle each commit and rollback, you may do so here as well.
const db = require('./connection');
const withTransaction = async (fn) => async (map) => {
const session = await db.conn.startSession();
await session.withTransaction(fn(map), { session });
session.endSession();
};
module.exports = withTransaction;
To call do something like this:
async function saveFunction(map) {
//.. implementation
const { var1, var2 } = map;
// use the var1, var2 here ....
// call mongodb CRUD here
}
// service call
const save = async (map) => {
withTransaction(saveFunction(map));
};
Hoping to get some comments so that I can improve this wrapper in the future.
Top comments (0)