Properly closing a connection once done with query - node.js

I am not sure how to close the connection once I'm done with my query
mongoose.connect("mongodb://localhost:27017/Settings", {
useNewUrlParser: true,
useUnifiedTopology: true,
useCreateIndex: true
});
SettingsModel.create({ guildID: guild.id } as Settings, (err: string, res: any) => {
if (err) return console.error(err);
console.log(res);
});

Unless there's a specific reason you want to close the connection, you shouldn't - Closing and opening connections is intensive and expensive. You open a connection once with and reuse it whilst your app is live.
It's advisable to close all connections when you shut down you app completely - you could do with
process.on('SIGINT', function() {
mongoose.connection.close(function () {
console.log('Disconnected db on app termination');
process.exit(0);
});
});

Related

Node.js/Express: How Do I Share or Export Mongo Database Connection To Other Modules?

I am trying to share the Mongo connection with other modules in my Node.js project. I keep getting either undefined or is not a function when attempting to use the exported client. I also had a question around detecting if the connection is in fact open before performing operations on the database.
It seems like using the app.locals would be the proper way to share the connection but I could not get that working either. Below is what I have at the moment. I've tried this many ways. Most of what I can find online seems to export the Mongo Node driver's method, not the connection itself. The idea is to connect once and never disconnect until the app shuts down.
const client = new MongoClient(uri, {
useNewUrlParser: true,
useUnifiedTopology: true,
});
async function connect () {
app.locals.dbConnected = false;
try {
await client.connect();
app.locals.dbConnected = true;
module.exports = client;
} catch (e) {
console.error(e);
}
};
then in another module do something like:
await client.db('syslogs').collection('production').insertOne(doc);
Is it possible to share the connection?
Could do something like below:
const client = new MongoClient(uri, {
useNewUrlParser: true,
useUnifiedTopology: true,
});
let __inst = null;
export default new Promise((resolve, reject) => {
if (__inst !== null) resolve(__inst);
// the open event is the key here
// like this we can handle error, close etc thru events as well
client.open((err, mongoInst) => {
if (err) reject(err);
__inst = mongoInst;
resolve(__inst);
});
});
Then in other module you can use the export client like you want.
Thanks.
I just got it working using app.locals.
index.js
const { MongoClient } = require("mongodb");
const client = new MongoClient(uri, {
useNewUrlParser: true,
useUnifiedTopology: true,
});
(async () => {
app.locals.dbConnected = false;
try {
await client.connect();
console.log("Connected to DB");
app.locals.client = client;
app.listen(PORT, HOST, () => {
console.log(`Running on http://${HOST}:${PORT}`);
});
} catch (e) {
console.error(e);
}
})();
Then in my module:
async function index (req, res) {
try {
let db = req.app.locals.client.db("admin");
await db.command({ ping: 1 });
console.log("pinged admin database");
}catch(err) {
console.log(err);
}
}

retry after MongooseServerSelectionError connection timed out

I want my nodejs application to retry after the inital connecton to mongoose fails. I connect to two separate databases in my application. Below is the code snippet for your reference.
function makeNewConnection(uri) {
const db = mongoose.createConnection(uri, {
useNewUrlParser: true,
useUnifiedTopology: true,
serverSelectionTimeoutMS: 180000
});
db.on('error', async function (error) {
console.log(`MongoDB :: connection ${this.name} ${JSON.stringify(error)}`);
db.close().catch(() => console.log(`MongoDB :: failed to close connection ${this.name}`));
});
db.on('connected', function () {
mongoose.set('debug', false);
console.log(`MongoDB :: connected ${this.name}`);
});
db.on('disconnected', function () {
console.log(`MongoDB :: disconnected ${this.name}`);
});
return db;
}
const localDBconnection = makeNewConnection(localDB);
const serverDBConnection = makeNewConnection(serverDB);
localDB and serverDB are my two connection uri's.
In case i retry with a timeout then it does not find the model instance. can someone suggest a clean way to do it.

How to make sure mongoose save callback is run before it disconnects when parsing csv?

New to node and can't seem to get past this. Trying to parse each row from a csv and save it into the db with mongoose.
csv.fromPath("tests.csv", { objectMode: true, headers: true, ignoreEmpty: true})
.on("data", function(data){
var test = new Test(data);
test.save(function(err, test) {
if(err) return console.error(err);
console.log(test);
console.log(test.name + ' saved!');
});
})
.on("end", function(){
mongoose.disconnect();
});
The console.log's won't work because mongoose disconnects before those callbacks are run:
{ [MongoError: server localhost:27017 sockets closed]
Your end handler is being called after the csv file has been parsed, but before you've saved the data to mongo. You could move the disconnect method into the save callback:
csv.fromPath("tests.csv", { objectMode: true, headers: true, ignoreEmpty: true})
.on("data", function(data){
var test = new Test(data);
test.save(function(err, test){
if(err) return console.error(err);
mongoose.disconnect()});
});
However, it's not the usual pattern to disconnect the mongoose connection after interacting with the database. If you have callbacks in your script, just call process.exit() in the final innermost or final one:
csv.fromPath("tests.csv", { objectMode: true, headers: true, ignoreEmpty: true})
.on("data", function(data){
var test = new Test(data);
test.save(function(err, test) {
if(err) console.error(err);
process.exit();
});
});
I don't think calling mongoose.disconnect() will terminate your script. Oh, and don't return on error, just log the error and exit the process. If you return on error the script won't terminate either.

Mongoose connection events with createConnection

I moved away from using the default connection to a explicitly defined connection.
My code is working except that none of the event handlers which track the state of my mongo connection are firing.
the events used to fire when I was using default mongoose connection. (mongoose.connect).
var mongoose = require('mongoose'),
logger = require('../logger'),
config = require('../config');
mongoose.connection.on('connecting', function(){
logger.info("trying to establish a connection to mongo");
});
mongoose.connection.on('connected', function() {
logger.info("connection established successfully");
});
mongoose.connection.on('error', function(err) {
logger.error('connection to mongo failed ' + err);
});
mongoose.connection.on('disconnected', function() {
logger.log('mongo db connection closed');
})
var gracefulExit = function() {
db.close(function(){
logger.log("mongoose connection with db " + server + 'is closing');
process.exit(0);
});
};
process.on('SIGNT', gracefulExit).on('SIGTERM', gracefulExit);
var db = mongoose.createConnection(config.get('DB_URL'));
module.exports = db;
the problem with the code is
None of the event handlers are firing.
Even the process events on SIGNT and SIGTERM are not firing.
I also tried
var db = mongoose.createConnection(config.get('DB_URL'));
db.on('connecting', function(){
logger.info("trying to establish a connection to mongo");
});
but this also doesn't fire.
i also faced with this problem,
and finally i solved it, after understood that the connect() / createConnection() execute before i declare the event handlers.
so the my open or connected events handlers will never called again.
so by declare them first and just after trying to connect - will solve your problem!
for example:
try {
mongoose.connection
.on('error', err => {
console.error(err);
})
.on('open', err => {
console.log(`DB connected`);
})
await mongoose.connect('mongodb://localhost:27017/test', { useNewUrlParser: true });
} catch (error) {
handleError(error);
}
This snippet blow work fine for me
const connection = mongoose.createConnection(`mongodb://${process.env.MONGO_URI}`);
connection.on('connected', () => {
console.log('connected to mongodb');
});
connection.on('disconnected', () => {
console.log('connection disconnected');
});
I just stumbled over this issue myself and found that I needed to set up the EventListeners before the actual connection to the database like so (with async/await):
export class Database {
public static connect( databaseCredentials: string ) {
return new Promise( async resolve => {
// ! The `EventListeners` is setup here.
mongoose.connection.on( "connected", () => {
logger.info( "Database has connected successfully." );
});
mongoose.connection.on( "error", (error) => {
logger.error( " Obs! There was an unexpected error connecting to the database.", error );
});
// ! The acutal connection to the database happens here.
await mongoose.connect( databaseCredentials, {
useNewUrlParser: true,
useUnifiedTopology: true,
keepAlive: true,
reconnectInterval: 500,
connectTimeoutMS: 10000,
});
resolve();
});
}
}
This should also work the same way with mongoose.createConnections.
This will yield the result (if successful):
{ message: 'Database has connected successfully.',
level: 'info',
timestamp: '2019-10-11T15:17:16.616Z' }
I just wanted to chip in and give my solution to the problem at hand and give a full example implementation of the code, as the above answers didn't explain in which order you needed to listen for the events. If you were to put the mongoose.connection.on() below the await.mongoose.connect(), this would not yield any response from the EventListeners.
Edit: Typos
try:
mongoose.connection.on('open', function() {
logger.info("database is ready now");
});
also temporary remove .close()

node js cluster mongoose connection

I am using nodejs built in cluster module in my application mongodb( not sharded) used for
storage in each cluster(worker) connection is made using mongoose.createConnection method and closes after inserting data.
But what i am expecting is whenever a request is made it opens connection to the db and process request and close the connection.
But what i noticed that when i checking the mongodb log still open connection and its count sligtly larger than no of processor/(cluster nodes).
and i put poolSize:1,autreconect:false still some connections are not closing even after close() method is called.
my observations are when connection error happends the connection is not closed
Please help me
I am using following script to get the connection .
module.exports.getDb = function () {
var dburl = 'mongodb://localhost/DB';
db = mongoose.createConnection(dburl, {
server: {
socketOptions: {
keepAlive: 1,
connectTimeoutMS: 30000
},
auto_reconnect: false,
poolSize: 1
}
}, function (err) {
console.log(err)
});
db.on('error', function (err) {
console.log(err + " this is error");
db.close();
});
return db;
}
and i close the conneciton using db.close() in the end of evey query callback.
Are you looking for something like this?
db.connection.on('error', function (e) {
console.log(e + " this is error");
db.close();
});
For my API server, I wrote a plugin for Hapi to handle this. Take a look, it might help you.
'use strict';
var bluebird = require('bluebird');
var mongoose = bluebird.promisifyAll(require('mongoose'));
exports.register = function(plugin, options, next) {
mongoose.connect(options.mongo.uri, options.mongo.options, function (e) {
if (e) {
plugin.log(['error', 'database', 'mongodb'], 'Unable to connect to MongoDB: ' + e.message);
process.exit();
}
mongoose.connection.once('open', function () {
plugin.log(['info', 'database', 'mongodb'], 'Connected to MongoDB # ' + options.mongo.uri);
});
mongoose.connection.on('connected', function () {
plugin.log(['info', 'database', 'mongodb'], 'Connected to MongoDB # ' + options.mongo.uri);
});
mongoose.connection.on('error', function (e) {
plugin.log(['error', 'database', 'mongodb'], 'MongoDB ' + e.message);
});
mongoose.connection.on('disconnected', function () {
plugin.log(['warn', 'database', 'mongodb'], 'MongoDB was disconnected');
});
});
return next();
};
exports.register.attributes = {
name: 'mongoose',
version: '1.0.0'
};

Resources