Raf Dor
Raf Dor

Reputation: 145

Mongo DB problem - connections accumulation

I have a problem with the approach I use to connect to Mondo DB.

I use the following method:

import { Db, MongoClient } from "mongodb";

let cachedConnection: { client: MongoClient; db: Db } | null = null;

export async function connectToDatabase(mongoUri?: string, database?: string) {
  if (!mongoUri) {
    throw new Error(
      "Please define the MONGO_URI environment variable inside .env.local"
    );
  }

  if (!database) {
    throw new Error(
      "Please define the DATABASE environment variable inside .env.local"
    );
  }

  if (cachedConnection) return cachedConnection;

  cachedConnection = await MongoClient.connect(mongoUri, {
    useNewUrlParser: true,
    useUnifiedTopology: true,
  }).then((client) => ({
    client,
    db: client.db(database),
  }));

  return cachedConnection!;
}

Everytime I need to connect to MongoDB I do as follows:

const { db } = await connectToDatabase(config.URI, config.USERS_DATABASE);
const myUniversity = await db
  .collection(config.MY_COLLECTION)
  .findOne({})

Everything seems ok, so what is the problem?

The problem is that the connections to my DB don't close after I use them. In fact I thought that my server is stateless so after every time i use my DB, the connections end. But it is not true! They stay alive, and after few hours of using my app mongo atlas sends me an email saying that the limit is exceeded.

As you can see in this screenshot, this chart is ever growing. That means that connections stay on and they accumulate. How do you think I can solve this problem?

enter image description here

Keep in mind that it uses cachedConnection only if I use the same connection. If I call a different API from the first one it creates another connection and it doesn't enter in if (cachedConnection) block, but it goes forward till the end.

Upvotes: 1

Views: 176

Answers (1)

prasad_
prasad_

Reputation: 14287

You can try this simple demo which will allow you to use the same connection throughout the application in different modules. There are three modules: the index.js is the starter program, the dbaccess.js is where you have code to create and maintain a connection which can be used again and again, and a apis.js module where you use the database connection to retrieve data.

index.js:

const express = require('express');

const mongo = require('./dbaccess');
const apis = require('./apis');

const app = express();

const init = async () => {
    await mongo.connect();
    app.listen(3000);
    apis(app, mongo);
};

init();

dbaccess.js:

const { MongoClient } = require('mongodb');

class Mongo {
    constructor() {
        this.client = new MongoClient("mongodb://127.0.0.1:27017/", {
            useNewUrlParser: true,
            useUnifiedTopology: true
        });
    }

    async connect() {
        await this.client.connect();
        console.log('Connected to MongoDB server.');
        this.db = this.client.db('test');
        console.log('Database:', this.db.databaseName);
    }
}

module.exports = new Mongo();

apis.js:

module.exports = function(app, mongo) {
    app.get('/', function(req, res) {
        mongo.db.collection('users').find().limit(1).toArray(function(err, result) {
            res.send('Doc: ' + JSON.stringify(result));
        });
    });
}

Change the appropriate values in the url, database name and collection name before trying.

Upvotes: 1

Related Questions