Reputation: 21
The problem is Mongoose loses its connection in the following scenario:
If I restart the Node JS app, all works fine.
Why is a failing query (using Mongoose version 4.4.5) to Mongo prevents the connection from being restored when the DB process is up again?
Should we implement a retry mechanism to try and restore the connection until DB becomes accessible?
I've tried the configuration mentioned here but it didn't work.
Any help would be appreciated.
Bellow is a sample code of our connection helper:
'use strict';
const _ = require('lodash');
const mongoose = require('mongoose');
const config = require('../config');
const logger = require('../logger');
const _instance = Symbol('instance');
const _enforcer = Symbol('enforcer');
const _members = Symbol('members');
/**
* Singleton implementation of ConnectionHelper module
* This module is responsible to reusing common db connections in the application
* @type {ConnectionsHelper}
*/
module.exports = class ConnectionsHelper {
constructor(enforcer) {
if (enforcer !== _enforcer) {
throw new Error('invalid singleton instantiation');
}
initConnectionFromConfig.call(this);
}
/**
* The single instance
* @returns {*}
*/
static get instance() {
if (!this[_instance]) {
this[_instance] = new ConnectionsHelper(_enforcer);
}
return this[_instance];
}
/**
* method retrieves connection by its name
* @param connectionKey
* @returns {*}
*/
getConnection(connectionKey) {
return this[_members][connectionKey];
}
/**
* method disconnects all underlying connections
* @returns {void|MongooseThenable}
*/
closeConnections() {
return mongoose.disconnect();
}
};
function initConnectionFromConfig() {
this[_members] = {};
const dbsConnections = config.get('dbsConnections');
_.forEach(dbsConnections, (connection, connectionName) => {
const protocol = connection.protocol;
const repSetPath = connection.mongoPath.join(',');
const options = connection.options;
options.server = {auto_reconnect: true, socketOptions: {keepAlive: 1, connectTimeoutMS: 30000 }};
options.replset = {socketOptions: {keepAlive: 1, connectTimeoutMS: 30000 }};
this[_members][connectionName] = mongoose.createConnection(protocol + repSetPath, options);
addConnectionEvents.call(this, connectionName);
});
}
function initConnectionIfNeeded() {
this[_members] = {};
const dbsConnections = config.get('dbsConnections');
_.forEach(dbsConnections, (connection, connectionName) => {
const protocol = connection.protocol;
const repSetPath = connection.mongoPath.join(',');
const options = connection.options;
//options.server = {auto_reconnect: true, socketOptions: {keepAlive: 1, connectTimeoutMS: 30000 }};
//options.replset = {socketOptions: {keepAlive: 1, connectTimeoutMS: 30000 }};
this[_members][connectionName] = mongoose.createConnection(protocol + repSetPath, options);
addConnectionEvents.call(this, connectionName);
});
}
function addConnectionEvents(connectionName) {
const connection = this[_members][connectionName];
connection.on('connected', () => {
logger.debug(`Mongoose connection open`);
});
connection.on('error', (err) => {
logger.debug(`Mongoose connection error: ${err}`);
});
connection.on('exception', (err) => {
logger.debug(`Mongoose connection exception: ${err}`);
});
connection.on('disconnected', () => {
logger.debug(`Mongoose connection disconnected`);
});
connection.on('reconnected', () => {
logger.debug(`Mongoose connection reconnected`);
});
connection.on('open', () => {
logger.debug(`Mongoose connection is open`);
});
// If the Node process ends, close the Mongoose connection
process.on('SIGINT', () => {
connection.close(() => {
logger.debug(`Mongoose default connection disconnected through app termination`);
process.exit(0);
});
});
}
Upvotes: 2
Views: 1205
Reputation: 870
I had the same problem. What I did is to restart mongoose in here:
connection.on('disconnected', () => {
logger.debug(`Mongoose connection disconnected`);
mongoose.connect(path);
});
And I also use setTimeout() so that it tries every 3 secs.
mongoose.connection.on('disconnected', function () {
console.log('Mongoose default connection disconnected');
console.log("Trying to reconnect");
function connect(){
mongoose.connect(dbPath, function(err){
if(err) console.log("Error while trying to reconnect to MongoDB");
});
}
setTimeout(connect, 3000);
});
And I also use ForeverJS.
Upvotes: 2