Using a mongo connection more than once returns Cannot use a session that has ended

Viewed 67

I'm having an issue using Mongo, consider:

const mongoose = require('mongoose');

const CONFIG = {
    host: "localhost",
    port: 27017,
    db: "dev"
};

const url = `mongodb://${CONFIG.host}:${CONFIG.port}/${CONFIG.db}`;
const options = {
    useNewUrlParser: true, 
    useUnifiedTopology: true, 
    useCreateIndex: true 
};

const checkMongoConnection = async () => {
    return new Promise(async (resolve, reject) => {
        if (mongoose.connection.readyState === 1) {
            return resolve();
        }

        try {
            await mongoose.connect(url, options);
            return resolve();
        } catch(error) {
            console.log(error);
            reject(error);
        }
    });
};

const disconnectMongo = async () => {
    return new Promise(async (resolve, reject) => {
        try {
            await mongoose.disconnect();
            return resolve();
        } catch(error) {
            console.log(error);
            reject(error);
        }
    });
};

module.exports = {
    checkMongoConnection,
    disconnectMongo
}

And my database query is like so:

const User = require('./app/Models/User');
const { checkMongoConnection, disconnectMongo } = require(
    './app/util/mongo-connection-util'
);

const task1 = async () => {
    try {
        await checkMongoConnection();

        const user = await User
            .findOne()

            console.log(user._id);

        await disconnectMongo();
    } catch(error) {
        console.log(error);
    }
};

task1()
task1()

The issue is that if I call a query the database with the task1 call and then query again immediately I get the error Cannot use a session that has ended. If I just call the function once there is no issue.

I understand that this is because the connection is already in use, the code would work if I utilised await and performed the functions in a serial manner, waiting for the first one to finish before performing the next.

However I want to do database calls after a group of API calls, so it will be async at different times. Is it possible to achieve this or do all database calls have to be one after another?

1 Answers

Unless you have documentation instructing differently, or an articulated use case that requires different behavior, you should create the driver's MongoClient object one time per process and use that object for the entire lifetime of the process.

In other words, remove all code that disconnects MongoClients.

If you want to have a MongoClient scoped to an operation, use the patterns provided in official documentation which don't involve storing the client globally.

Related