DEV Community

Rodel Talampas
Rodel Talampas

Posted on

Singleton Connection with Transactions in MongoDB

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();
Enter fullscreen mode Exit fullscreen mode

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;
Enter fullscreen mode Exit fullscreen mode

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));
};
Enter fullscreen mode Exit fullscreen mode

Hoping to get some comments so that I can improve this wrapper in the future.

Sentry image

Hands-on debugging session: instrument, monitor, and fix

Join Lazar for a hands-on session where you’ll build it, break it, debug it, and fix it. You’ll set up Sentry, track errors, use Session Replay and Tracing, and leverage some good ol’ AI to find and fix issues fast.

RSVP here →

Top comments (0)

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay