How to get node to exit when mongo connect fails - node.js

I'd like my Node JS app to exit immediately if it can't connect to Mongo. I'm using the mongodb node library.
I've reduced the code down to
const {MongoClient} = require('mongodb');
MongoClient.connect('mongodb://localhost:27017');
If Mongo is not running, I get an UnhandledPromiseRejectionWarning with ECONNREFUSED, which I fully expect, but then the program hangs and never exits. This is with Node version 10.0.0.
Since the connection never succeeded I don't have a connection handle to close. I've tried various ways to catch the rejected promise, but I have been unsuccessful in getting the program to exit.
What do I need to do to shut down the MongoClient and make the program exit in this case?

Your application is remaining alive because it is trying to reconnect. You can try disabling the recconect:
MongoClient.connect('mongodb://localhost:27017', {
autoReconnect: false
}, (err, client) => {
if (client) client.close();
});
Or, you can terminate the process using process.exit(1) to kill the program.
const {
MongoClient
} = require('mongodb');
// Callback syntax
MongoClient.connect('mongodb://localhost:27017', (err, db) => {
if (err) process.exit(1);
});
// Promise syntax
MongoClient
.connect('mongodb://localhost:27017')
.catch(err => {
process.exit(1);
});
// Async/await syntax
(async function() {
let db;
try {
db = await MongoClient.connect('mongodb://localhost:27017');
} catch (err) {
process.exit(1);
}
}());

Related

Node js can't connect to my database using mongoose

I am trying to use use hyper terminal to connect to my mongodb database (created with mongoose) and when I use node app.js to try to connect to the database using hyper terminal, my terminal just freezes and return no response until I press ctrl c to exit and return to the previous line.
My mongoose code looks like the following:
const mongoose = require('mongoose');
mongoose.connect('mongodb://127.0.0.1:27017/fruitsDB');
Please note. I have already connected to the mongodb server by using mongodin the terminal and I have also cd to the directory of my folder where the app.js is located on my pc before running the node app.js on the terminal
screenshort of my terminal hyerterminal code screen
Please I need your help. Thank you
I believe that your terminal is NOT frozen, it is just that there is no console output in your code. You are connecting to Mongoose and then doing nothing after that.
Here are some suggestions,
You can use a callback to check if the connection is connected,
mongoose.connect('mongodb://127.0.0.1:27017/fruitsDB').then(
() => {
console.log("Connected to DB!");
},
err => {
console.log(err);
}
);
Add a few event handlers to check if your connection is working,
mongoose.connection.on('open', function(){
console.log("Connection to Mongo DB is open!");
});
If you want to check for errors during "connect", you can chain an error handler in catch block.
mongoose.connect('mongodb://localhost:27017/test').
catch(error => console.log(error));
If you want to use Async/Await for the same error handling, then follow the below.
(async () => {
try {
await mongoose.connect('mongodb://localhost:27017/test');
console.log("Successfully connected to Mongo DB");
} catch (error) {
console.log(error);
}
})();
If you want to catch errors happening after the connection is connected to Mongo DB,
mongoose.connection.on('error', err => {
console.log(error);
});

How to deal with connection lost to DB in NodeJS Express App

I am developing an express application which connects to a MongoDB database. It is possible that my express server looses the connection to database, but how should my express server react to this scenario? I prepared the following code where i check for a lost connection and then I kill the app.
const registerCustomer = async (req, res) => {
let validRegistrationCode;
try {
validRegistrationCode = await CustomerRegistrationCode.findOne({ code: req.body.code });
} catch (error) {
if (error instanceof MongoNetworkError || error instanceof MongooseServerSelectionError) {
console.error('Mongo | Mongoose Network Error occurred');
}
process.exit(1);
}
return res.json({ obj: validRegistrationCode });
}
For every access to the DB, I have to check for a connection error and I think this makes the code ugly. How can this be improved?
I think the failure of connection to mongoDB usually doesn't happen or it can also happen in case of network is loss, or your path, syntax is not correct and what you should do is check only once when setup mongoose to connect to your database, every time you save code nodemon will help you check if you have successfully connected
// connect model with database
const mongoose = require('mongoose');
async function connect() {
try {
await mongoose.connect('mongodb://localhost:27017/collections_clothes', {
// useNewUrlParser: true,
// useUnifiedTopology: true,
// useCreateIndex: true,
});
console.log("Access Database Success!");
} catch (error) {
console.log("Access FAIL!");
}
}
module.exports = { connect };

Nodemon start only webserver (not db server) in Node

I am using nodemon to restart my node application when ever changes were made. My problem is every time both web-server and DB server are restarting after code changes were made. I am using Oracle DB. below is my app.js code:
const webServer = require('./services/web-server.js');
const database = require('./services/database.js');
const dbConfig = require('./config/database.js');
const defaultThreadPoolSize = 4;
async function startup() {
console.log('Starting application');
//Initializing web server module
try {
console.log('Initializing web server module');
await webServer.initialize();
} catch (err) {
console.error(err);
process.exit(1); // Non-zero failure code
}
//Initializing the Oracle DB
try {
console.log('Initializing database module');
await database.initialize();
} catch (err) {
console.error(err);
process.exit(1); // Non-zero failure code
}
//Stopping Oracle DB
/*try {
console.log('Closing database module');
await database.close();
} catch (err) {
console.log('Encountered error', e);
err = err || e;
}*/
}
startup();
services/web-server.js, I am creating a http server like below:
httpServer = http.createServer(app);
services/database.js, I am creating a pool for Oracle:
const pool = await oracledb.createPool(dbConfig.hrPool);
Please suggest me how can I restart only web-server with nodemon? I don't want DB connection to restart always...
Your database server doesn't restart every time you restart your node application.
What's happening is your node is recreating the connection to the database every time it's restarted, which is normal and can't be avoided.
You can check this by connecting to your Oracle server and doing queries on it while your node application is stopped.

Node module; Mongod not returning promise at all?

I'm using mongod
module to start a MongoDB server for my node.js app.
I'm quite new to programming and after some googling I think it is the best I could come up with.
In mongod documentation, Mongod#open() returns a promise, which I believe I consume correctly.
However, my code never gets to the point where the client connects and I can't spot what I did wrong.
Here's my code:
const
Mongod = require('mongod'),
MongoClient = require('mongodb').MongoClient,
config = require('./config');
const
mongoURI = 'mongodb://localhost:27017/' + config.db.table_name,
server = new Mongod({
conf: config.db.path_to_cfg
});
const connectToDB = (uri) => {
return MongoClient.connect(uri);
};
//If mongod service is not running, create a new server and connect
console.log(server.isRunning); //Just to verify
if (!server.isRunning) {
console.log('dbConnect:: Starting MongoDB server...');
server.open()
.then(() => {
connectToDB(mongoURI)
.then((db) => {
console.log(db)
})
.catch((err) => {
console.log('Error: ' + err)
})
})
} else {
connectToDB(mongoURI)
.then((db) => {
console.log(db)
})
.catch((err) => {
console.log('Error: ' + err)
})
}
dbConnect:: Starting MongoDB server... logs in the console, the server runs successfully, since I can connect from windows CLI and query the database, but .then() is not executed and db is not logged.
I have tested the else block it is working as it should, (which also means my config module is correct) logging the db object when I have previously started the server from CLI.

How do I ignore redis if it is not available?

I want my application (lets say a simple node file for now) to work as it is even if redis is not available. I'm not able to do it the correct way. This is what I've tried.
var redis = require('redis');
var redisClient = null;
var getRedisClient = function(){
if(redisClient){
return redisClient;
}
try {
redisClient = redis.createClient({connect_timeout : 5000, max_attempts : 1});
redisClient.on("error", function(err) {
console.error("Error connecting to redis", err);
redisClient = null;
});
return redisClient;
} catch(ex){
console.log("error initialising redis client " + ex);
return null;
}
};
try {
var client = getRedisClient();
console.log("done!");
} catch (ex){
console.log("Exception");
}
However, with this code my application exits if redis is not available (it shouldn't because i've not given a process.exit() command).
How can I solve this?
Checking for Successful Connection on Start
Using a promise, you could guarantee that at least initially, you were able to connect to redis without error within a specified time period:
const redis = require('redis');
const Promise = require('bluebird');
function getRedisClient(timeoutMs){
return new Promise((resolve, reject) => {
const redisClient = redis.createClient();
const timer = setTimeout(() => reject('timeout'), timeoutMs);
redisClient.on("ready", () => {
clearTimeout(timer);
resolve(redisClient);
});
redisClient.on("error", (err) => {
clearTimeout(timer);
reject(err);
});
});
};
const redisReadyTimeoutMs = 10000;
getRedisClient(redisReadyTimeoutMs)
.then(redisClient => {
// the client has connected to redis sucessfully
return doSomethingUseful();
}, error => {
console.log("Unable to connect to redis", error);
});
You Need Proper Error Handling
The redis client being non-null does NOT guarantee using it won't throw an error.
you could experience infrastructure misfortune e.g. crashed redis process, out of memory or network being down.
a bug in your code could cause an error e.g. invalid or missing arguments to a redis command.
You should be handling redis client errors as a matter of course.
DON'T null the Redis Client on Error
It won't give you much but it will force you to check for null every time you try and use it.
The redis client also has inbuilt reconnect and retry mechanisms that you'll miss out on if you null it after the first error. See the redis package docs, look for retry_strategy.
DO Wrap your redis client code with try .. catch ... or use .catch in your promise chain.
DO Make use of a retry_strategy.

Resources