0

I'm running Express NodeJS in GCP App Engine Standard, with MongoDB hosted in Atlas. My observation is when I declare the Mongoose Connection globally with no explicit Close, the connections keep mounting up until it hits the limit of 100.

My assumption is that, since this is GCP App Engine Standard which is running by Instance, each Method call might be running its own Instance and connection is not pooling. So instead of Global MongoDB Connection, each method will have its local connection instead.

So then code was updated to the following:

router.post('/subscribe',function(req,res,next){               
    var email = req.body.email
    if(email&&email!=''){
                let mongoose = require('mongoose')
                mongoose.connect(process.env.MONGODBHOST).then(resp=>{                  
                        Subscribers.findOne({"email":email},function(error,results){
                                if(!results){ 
                                        var newSubscriber = new Subscribers({
                                                email: email
                                        })
                                        newSubscriber.save().then(resp=>{
                                                console.log('Subscriber added')
                                                if(mongoose.connection){
                                                        mongoose.connection.close(true).then(r=>{}).catch(e=>{})
                                                }
                                                res.status(200).send({ success: true, message: 'Added' })
                                        }).catch(err=>{
                                                console.log(err)
                                                if(mongoose.connection){
                                                        mongoose.connection.close(true).then(r=>{}).catch(e=>{})
                                                }
                                                res.status(200).send({ success: false, message: err })
                                        })
                                } else {
                                        console.log('Subscriber existing')
                                        if(mongoose.connection){
                                                mongoose.connection.close(true).then(r=>{}).catch(e=>{})
                                        }
                                        res.status(200).send({ success: true, message: 'Existing' })
                                }               
                        })         
                }).catch(err=>{                 
                        res.status(200).send({ success: false, message: 'DB connection failed' })
                })              
    } else {
        console.log('No email found')
        res.status(200).send({ success: false, message: 'No parameter found' })
    }
})

Another method also exists that takes relatively longer than the method above

router.post('/getDetails',function(req,res,next){               
                let mongoose = require('mongoose')
                mongoose.connect(process.env.MONGODBHOST).then(resp=>{                  
                        Transactions.find({"active":true},function(error,results){
                                if(!results){ 
                                    if(mongoose.connection){
                                         mongoose.connection.close(true).then(r=>{}).catch(e=>{})
                                    }
                                    res.status(200).send({ success: false, message: err })

                                } else {                                  
                                    if(mongoose.connection){
                                         mongoose.connection.close(true).then(r=>{}).catch(e=>{})
                                    }
                                    res.status(200).send({ success: true, message: 'Existing' })
                                }               
                        })         
                }).catch(err=>{                 
                        res.status(200).send({ success: false, message: 'DB connection failed' })
                })              
})

If run independently, it works fine, but sometimes, if run at exactly the same time, the second function sometimes throws an error that says: "Pool force destroyed"

For some reason, it seems like the Connection.close() from Function1 affected the MongoDB connection in GetDetails even though Mongoose is local to each Method.

Please advise what is the best approach in this set up.

Thanks!

Adrian Borja
  • 144
  • 2
  • 13
  • 2
    So, **properly** would begin with not creating connections within request handlers. Read the answers, where part of the irony is that you are actually already using mongoose, but just not realizing your application only needs that `mongoose.connect()` statement **once**. Bottom line is database connections need to persist for the lifecycle of your application. You are not meant to connect and disconnect within each request. It's certainly slowing down your application performance dramatically by doing so at the very least, but in larger request volumes you see the results you have now. – Neil Lunn Sep 30 '19 at 02:56
  • 2
    I will note that is might be *possible* your App Engine instances are spawning to a rate where the connection pools allocated on each instance quickly add up to a large number of total connections. However this would really become about managing the instance spawning, and quite probably allowing more requests per instance mitigating how many are actually spawned. But of course that's all "server configuration" and not actually a programming topic suitable to this site. The *programming* approach is well documented. – Neil Lunn Sep 30 '19 at 03:25
  • thanks for highlighting the necessity of not connecting and disconnecting per request. My original code is actually built this way. Then maybe I need to figure out why the connections are not pooling. Could be a GCP bug or more likely a free tier limitation – Adrian Borja Sep 30 '19 at 08:00
  • Reference answer actually helped. In my case, i used the express-mongo-db. connect happens in the router level, not in individual routes, and connections are not skyrocketing now, and app is noticeably faster. thanks – Adrian Borja Oct 11 '19 at 06:10

0 Answers0