简体   繁体   中英

MongoDB: Async function doesn't end on complete or how to close connection properly with mongoose

This problem is more relevant to MongoDB and mongoose driver, not the async/await code itself.

I have the following code in my *.js file:

const model1 = require("../../db/model1");
const model2 = require("../../db/model2");
const {connection} = require('mongoose');

async function f() {
    try {
        let token = await model2.findById(id) //find just one doc 
        let cursor = await model1.find({}).limit(5).cursor()
        for (let c = await cursor.next(); c != null; c = await cursor.next()) {
            //BLAH BLAH BLAH LOGIC
        }  
    } catch (e) {
        console.log(e)
    }  
}

f().then(r => {
    connection.close();
    console.log('close');
    return r
});

So the problem is:

When I am using just one model with require (CommonJS) the function ends properly with the following message: Process finished with exit code 0 , but when I add the second model to the file ( model2 in my case, but it could be any model file or another function with require model ) then function doesn't end.

It doesn't mean that connection.close() doesn't work, according to debug console of WebStorm it does, message close from console.log() prints successfully, but for some reason the process doesn't end at all. I have seen on SO other questions about connection.close like this one , but none of them have been relevant to my problem. Docs said that one close() is enough and it closes all the connections in a pool.

Every model that I import have the following structure, without any exceptions:

const mongoose = require('mongoose');
mongoose.Promise = global.Promise;

require('dotenv').config();
mongoose.connect(`mongodb://${process.env.login}:${process.env.password}@${process.env.hostname}/${process.env.auth_db}`, {
    useNewUrlParser: true,
    useFindAndModify: false,
    useUnifiedTopology: true,
    bufferMaxEntries: 0,
    retryWrites: true,
    useCreateIndex: true,
    w: "majority",
    family: 4
});

let schema = new mongoose.Schema({
    _id: {
        type: String
    },
    any_field: {
        type: String,
    },
},{
    timestamps: true
});

let keys_db = mongoose.model('keys', schema);

module.exports = keys_db;

Cause model code doesn't have any setTimeout or other function except connect to DB it shouldn't block the thread. So I can't understand what's going wrong with that and I guess someone on SO have already face the similar problem and could provide some clarification to me. Or it a normal behavior of async function and I shouldn't see a problem in it?

As I found it, using connect in every model is a bad practice. Unfortunately, it's very poorly described in mongoose manual.

As a result, it's a problem of a bad architecture in my project. So, the correct answer lies below:

Instead of using connect in every schema/model file, you should (use) connect just once and then export it

Or make a separate connection for every core/sensitive function for example, separate connection for back-end and front-end but not every connection for every function (like I did)

As I mention before, mongoose docs describe this pattern very poor, and documentation for connection.close() describe this method, like you could close all-connections-at-once. (Which is actually true, but it won't help you in that case)

I also found this questions on Stack Overflow very useful in my research:

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM