Mongoose Close Connection - node.js

I have A Mongoose Connection and at some point in my program I need to close it.
after logging the mongoose object several times, I have found that the following workd
mongoose.connection.base.connections[1].close();
Is There A Cleaner way to do this?

To close all connections in the Mongoose connection pool:
mongoose.disconnect();
Docs here.

I used a singleton in my code.
Exporting a promise
In one file I export a promise...
connection.js
const { createConnection } = require('mongoose');
function getConnection() {
return mongoose.createConnection(...).asPromise();
}
const connPromise = getConnection();
module.exports = connPromise;
other files...
const connPromise = require('./connection.js');
async function handler() {
// Connection starts on first module import
// This gets faster when the connection is done being created
const connection = await connPromise;
// Do stuff with the connection
return {
data: '',
and: '',
stuff: '',
};
}
When everything is shutting down, like in a lambda, also in connection.js:
process.on('SIGTERM', async () => {
console.info('[runtime] SIGTERM received');
const conn = await connPromise;
await conn.close();
console.info('[runtime] closed connection');
process.exit(0);
});
So by storing the connection in a promise, I can get it everywhere. I don't export the connection itself because getting it is async.
Exporting a getter function
I could have a function like
let connection = null;
function getConnection() {
if (!connection) {
connection = await createConnection(...).asPromise();
}
return connection;
}
module.exports = getConnection;
other files...
const getConnection = require('./connection.js');
async function handler() {
// Gets faster after the first call.
// connection created on first call.
const connection = await getConnection();
// Do stuff with the connection
return {
data: '',
and: '',
stuff: '',
};
}
Then your shutdown would become
process.on('SIGTERM', async () => {
console.info('[runtime] SIGTERM received');
if (connection) {
await connection.close();
console.info('[runtime] closed connection');
}
process.exit(0);
});
Summary
Overall, I like exporting the promise, since in every lambda function, I'm always using the database.
Since the exported promise means that the connection starts as soon as the module is imported, it's ready to go sooner than if I waited till the invocation of the getConnection() in an event handler.
For having only one connection, this is a good way to get ahold of it.

Related

Using async/await with Mongoose recent version(6.2.7)

I have the following code to connect to Mongoose DB using Node.js. But I get some kind of warning or refactor notification from VS code to remove await from the the part when I try to connect.
Its say that: await has no effect in this kind of expression
From the documentation of Mongoose inside index.d.ts file;
export function connect(uri: string, options?: ConnectOptions): Promise<Mongoose>; returns promise
So I try to do like this:
// Provide connection to a new in-memory database server.
const connect = async () => {
// NOTE: before establishing a new connection close previous
await mongoose.disconnect()
mongoServer = await MongoMemoryServer.create()
try {
const mongoUri = await mongoServer.getUri()
await mongoose.connect(mongoUri, opts) // No need to use await??
} catch (error) {
console.log(error)
}

node-postgres script does not end after it is finished

I have a script called scheduler() which runs some queries on a Postgres database and then finished. I am having a problem where the script hangs in the terminal and does not exit after.
Here is my code:
scheduler.js
const {pool} = require("./db");
const scheduler = async function() {
try {
await auctionCheck();
return pool.end().then(() => {
console.log('Pool\'s closed');
return;
})
} catch (e) {
console.error(e)
return;
}
}
return scheduler();
db.js
const {Pool} = require("pg");
const pool = new Pool({
connectionString: process.env.DATABASE_URL,
});
pool.on('error', (err, client) => {
console.error('Unexpected error on idle client', err)
process.exit(-1)
})
pool.connect();
module.exports = {pool};
When I didn't have the pool.end() call, my script didn't exit, but it does not exit with the end() call either. The "Pool's closed" log is never printed. node-pg documentation says that I should do this to close connections (I assume that the reason my script isn't finishing is due to an open db connection.) I want to basically run some functions periodically and then have the script finish, but currently it just stays live. What am I doing wrong?
It seems that the reason was that in db.js I had pool.connect(). Thus, when I did pool.end(), it couldn't close the connection because it did not have all of the clients in the pool - one being already created in db.js but never released. When I removed pool.connect() in db.js the process exited as it should.

Not sure why node is continuously running

I can't figure out why this app keeps running. I've tried using the why-is-node-running package but I'm not perfectly sure how to read the output properly. Here's the first output of it:
There are 30 handle(s) keeping the process running
# TCPWRAP
/node_modules/mongodb/lib/core/connection/connect.js:269 - socket = tls.connect(parseSslOptions(family, options));
/node_modules/mongodb/lib/core/connection/connect.js:29 - makeConnection(family, options, cancellationToken, (err, socket) => {
/node_modules/mongodb/lib/core/sdam/monitor.js:182 - connect(monitor.connectOptions, monitor[kCancellationToken], (err, conn) => {
/node_modules/mongodb/lib/core/sdam/monitor.js:206 - checkServer(monitor, e0 => {
/node_modules/mongodb/lib/core/sdam/monitor.js:92 - monitorServer(this);
My guess is it has something to do with MongoDB not closing properly. Although, when I removed all of the other functions between opening the client and closing it, it opened and closed perfectly.
Adding process.exit() at the end closes program properly, but I'd like to figure out why it isn't closing.
A summary of the app is that it is getting data from MongoDB, cleaning it, and then writing it into Firestore - so a lot of async actions going on, but I didn't see Firestore-related stuff pop up in the why-is-node-running logs.
const GrabStuffFromDBToCalculate = require("./helpers/GrabStuffFromDBToCalculate");
const SendToFirestore = require("./helpers/SendToFirestore");
const log = require("why-is-node-running");
const { MongoClient } = require("mongodb");
require("dotenv").config();
const main = async () => {
try {
const client = await MongoClient.connect(process.env.MONGODB_URI, {
useNewUrlParser: true,
useUnifiedTopology: true
});
const collection = await client.db("test").collection("testcollection");
const trip_object = await GrabStuffFromDBToCalculate(collection);
SendToFirestore(trip_object);
client.close();
log(); // "There are 30 handle(s) keeping the process running including node_modules/mongodb/lib/core/connection/connect.js:269 - socket = tls.connect(parseSslOptions(family, options));"
// process.exit() // this closes everything but I'd rather not have to use this
} catch (err) {
console.log(err);
client.close();
}
};
const runAsync = async () => {
await main(); // this exists because I'm usually running multiple main() functions
};
runAsync();
SendToFirestore code:
const firebase = require("firebase");
const firebaseConfig = require("../config");
module.exports = SendToFirestore = trip_object => {
if (!firebase.apps.length) {
firebase.initializeApp(firebaseConfig);
}
const db = firebase.firestore();
db.doc(`hello/${object._id}`).set({
objectid:object._id
});
};
GrabStuffFromDBToCalculate code (way simplified):
module.exports = GrabStuffFromDBToCalculate = async collection => {
const cursor = await collection
.aggregate([
// does a bunch of stuff here
])
.toArray();
const newObj = cursor[0];
return newObj;
};
Making my comment into an answer since it led to the missing piece.
Node does not shut down because you have an open Firestore connection. You will have to call terminate to allow the SDK to shut down and release resources:
db.terminate();
Which is relevant for allowing nodejs to shut itself down automatically.
Also, I'm not sure you understood that I was suggesting that you use await as in
await client.close()
before calling log() so you are sure that the client connection has been closed before you do the logging. client.close() is an asynchronous method so your original code would log() before that close was complete.

How to use async/await with mongoose

In node.js I had code like following:
mongoose.connect(dbURI, dbOptions)
.then(() => {
console.log("ok");
},
err => {
console.log('error: '+ err)
}
);
Now i want to do it with async/await syntax. So i could start with var mcResult = await mongoose.connect(dbURI, dbOptions);, afaik it will wait for operation, until it ends with any result (much like calling C function read() or fread() in syncronous mode).
But what should I write then? What does that return to the mcResult variable and how to check for an error or success? Basically I want a similar snippet, but written with proper async/await syntax.
Also I wonder because I have auto reconnect, among dbOptions:
dbOptions: {
autoReconnect: true,
reconnectTries: 999999999,
reconnectInterval: 3000
}
Would it "stuck" on await forever, in case if database connection is unavailble? I hope you can give me a clue on what would happen and how that would work.
Basically I want a similar snippet, but written with proper async/await syntax.
(async () => {
try {
await mongoose.connect(dbURI, dbOptions)
} catch (err) {
console.log('error: ' + err)
}
})()
Please try this, Below code has basics of db connectivity and a query :
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
let url = 'mongodb://localhost:27017/test';
const usersSchema = new Schema({
any: {}
}, {
strict: false
});
const Users = mongoose.model('users', usersSchema, 'users');
/** We've created schema as in mongoose you need schemas for your collections to do operations on them */
const dbConnect = async () => {
let db = null;
try {
/** In real-time you'll split DB connection(into another file) away from DB calls */
await mongoose.connect(url, { useNewUrlParser: true }); // await on a step makes process to wait until it's done/ err'd out.
db = mongoose.connection;
let dbResp = await Users.find({}).lean(); /** Gets all documents out of users collection.
Using .lean() to convert MongoDB documents to raw Js objects for accessing further. */
db.close(); // Needs to close connection, In general you don't close & re-create often. But needed for test scripts - You might use connection pooling in real-time.
return dbResp;
} catch (err) {
(db) && db.close(); /** Needs to close connection -
Only if mongoose.connect() is success & fails after it, as db connection is established by then. */
console.log('Error at dbConnect ::', err)
throw err;
}
}
dbConnect().then(res => console.log('Printing at callee ::', res)).catch(err => console.log('Err at Call ::', err));
As we're talking about async/await then few things I wanted to mention - await definitely needs it's function to be declared as async - otherwise it would throw an error. And it's recommended to wrap async/await code inside try/catch block.
const connectDb = async () => {
await mongoose.connect(dbUri, dbOptions).then(
() => {
console.info(`Connected to database`)
},
error => {
console.error(`Connection error: ${error.stack}`)
process.exit(1)
}
)
}
connectDb().catch(error => console.error(error))
Lets assume the use of then() is prohibited, you can result to this...
const connectDb = async () => {
try {
await mongoose.connect(dbConfig.url, dbConfigOptions)
console.info(`Connected to database on Worker process: ${process.pid}`)
} catch (error) {
console.error(`Connection error: ${error.stack} on Worker process: ${process.pid}`)
process.exit(1)
}
}

Need example of using Promise in node.js

I need an example how to use promise in node.js. I have a variable connection that must be closed after a call to function finished. Here is the flow how my program should run
var connection = {
/*create connection */
}
/* call to a function */
/* close connection after function finish */
connection.close();
This is an example using bluebird (http://bluebirdjs.com/docs/getting-started.html)
let con = undefined
Promise.try(() => createConnection()) // create connection
.then(_con => {
con = _con // assign connection
// TO DO STUFF
})
.then(() => {
con.close() // close connection
})
.catch(e => {
// handle exception here
})

Resources