Nodemon start only webserver (not db server) in Node - node.js

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.

Related

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 };

How to get node to exit when mongo connect fails

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);
}
}());

Make node wait for mongoDB to start

I use pm2 to start my database and my express node web server together. When I start them with pm2 start all it works fine; mongod starts before node and it can connect. But when I use pm2 reload all node fails to connect to the database because it tries to connect before mongod has completely initialized. This is basically the same as starting the web server and not mongod.
How can I make the web server retry connecting to mongod if it fails? There is a feature called reconnect in the node mongo driver but it only applies to loss of connection if there was a connection before.
on error, you can call another connection function, or if you use promises, you can use a standard loop to retry.
//call the following in an async function
var db = null
while (db === null) {
try {
db = await Promise((resolve, reject) => {
MongoClient.connect("mongodb://localhost:27017/MyDb", function (err, db) {
if (err) reject(err);
resolve(db)
})
})
//insert a sleep so you're waiting a bit to reconnect
} catch (e) {
console.log(e)
}
}

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