I have tried this way -
const server = app.listen(port, () => console.log('Project running on port ' + port));
process.on('SIGINT', () => {
console.info('SIGINT signal received.')
// Stops the server from accepting new connections and finishes existing connections.
server.close(function(err) {
// if error, log and exit with error (1 code)
if (err) {
console.error(err)
process.exit(1)
}
// close your database connection and exit with success (0 code)
// for example with mongoose
mongoose.connection.close(function () {
console.log('Mongoose connection disconnected')
process.exit(0)
})
})
})
And 2nd This way too -
const server = app.listen(port, () => console.log('Project running on port ' + port));
process.on('message', function(msg) {
console.info('shutdown signal received.',msg)
if (msg == 'shutdown') {
console.log('Closing all connections...');
setTimeout(function() {
console.log('Finished closing connections');
process.exit(0);
}, 1500);
}
});
But Neither is helping.
What I understand from reading all the related open alike issue is PM2 rather sending 'SIGINT' signal to node, it killing it by themself.
Instead of using pm2 we can self make a bash script that will restart our node project if shut with some error.
@echo off
setlocal enableextensions enabledelayedexpansion
set /a "x = 0"
:more_to_process
if %x% leq 10 (
echo %x%
node E:\Max\Projects\dummy\API\server.js
set /a "x = x + 1"
goto :more_to_process
)
endlocal
pause
Above script retry 10 times to restart the API. One can change the retry time.
Now for making the log files and handling the errors, we can do
const server = app.listen(port, () => console.log('Dummy-App API running on port ' + port));
var fs = require('fs');
var util = require('util');
var path = __dirname + `/mylogfiles/debug(${getDate()}).log`, printNextLine = false
if(fs.existsSync(path)){
printNextLine = true
}
var log_file = fs.createWriteStream(path, {flags : 'a'});
/* 'a' : open the file for writing, positioning the stream at the end of the file. The file is created if not existing
'a+' : open the file for reading and writing, positioning the stream at the end of the file. The file is created if not existing
'r+' : open the file for reading and writing
'w+' : open the file for reading and writing, positioning the stream at the beginning of the file. The file is created if not existing
(you can find more flags at https://nodejs.org/api/fs.html#fs_file_system_flags)
*/
if(printNextLine == true){
let prnt = '***************************************************************************************************************'
log_file.write('\n' + '\n' + prnt + '\n');
}
var log_stdout = process.stdout;
console.log = function(d) { //
log_file.write((new Date).toLocaleString('en-IN', { timeZone: 'Asia/Kolkata' }) + ' | ' + util.format(d) + '\n');
log_stdout.write( util.format(d) + '\n');
};
console.error = function(d) { //
log_file.write((new Date).toLocaleString('en-IN', { timeZone: 'Asia/Kolkata' }) + ' | ' + util.format(d) + '\n');
log_stdout.write( util.format(d) + '\n');
};
process.on('uncaughtException', function (err) {
console.error(err)
// console.error((new Date).toUTCString() + ' uncaughtException:', err.message)
// console.error(err.stack)
process.exit(1)
})
function getDate(addDay){
let mydate = new Date()
var month = mydate.getMonth() + 1; // month (in integer 0-11)
var year = mydate.getFullYear(); // year
var date = mydate.getDate()
let h = mydate.getHours()
let m = mydate.getMinutes()
let s = mydate.getSeconds()
// let desiredDate = `${year}.${month}.${date} H-${h} M-${m} S-${s}`
let desiredDate = `${year}.${month}.${date}`
return desiredDate
}
Now, what is remaining to "Graceful Shutdown":-
process.on('SIGINT', () => {
console.info('SIGINT signal received.')
// Stops the server from accepting new connections and finishes existing connections.
server.close(function(err) {
// if error, log and exit with error (1 code)
if (err) {
console.error(err)
process.exit(1)
}
// close your database connection and exit with success (0 code)
// for example with mongoose
mongoose.connection.close(function () {
console.log('Mongoose connection disconnected')
process.exit(0)
})
})
})
About code process.on('SIGINT', ..
will help if we run/start Node.js API with command
node server.js
or the file index.js whatever is have named it.
That's why we built our Bash script that will take 'node' as a command to start the project-API. One can put that bash script anywhere on the system/server unless and until path given on bash script for starting the API main file is correct.
Finally, the main server.js/index.js file may look like -
const express = require('express');
const bodyParser = require('body-parser'); // call body-parser here to parse body request from frontend
var fileUpload = require('express-fileupload'); // call express-fileupload here to accept file in the form of multipart data from frontend
// create express app
const app = express();
// parse requests of content-type - application/json
app.use(bodyParser.json({limit:'50mb'})); // here we try to set body request can accept requested data from frontend upto 50Mb
// parse requests of content-type - application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: true,limit:'50mb' })); // here we try to set body request can accept requested data from frontend as urlencoded and upto 50Mb
app.use(fileUpload()); // here enable app to use fileupload
// Configuring the database
const dbConfig = require('./config/database.config.js');
const mongoose = require('mongoose');
mongoose.Promise = global.Promise;
const options = {
auth: {
user: "*********ww",
password: "******dd"
},
useNewUrlParser: true,
useCreateIndex: true,
useFindAndModify: false,
autoIndex: true, // Don't build indexes
reconnectTries: Number.MAX_VALUE, // Never stop trying to reconnect
reconnectInterval: 500, // Reconnect every 500ms
poolSize: 10, // Maintain up to 10 socket connections
// If not connected, return errors immediately rather than waiting for reconnect
bufferMaxEntries: 0,
connectTimeoutMS: 10000, // Give up initial connection after 10 seconds
socketTimeoutMS: 45000, // Close sockets after 45 seconds of inactivity
family: 4, // Use IPv4, skip trying IPv6
serverSelectionTimeoutMS: 5000, // Timeout after 5s instead of 30s
useUnifiedTopology: true
};
mongoose.connect(dbConfig.url, options).then(
() => {
console.log("Successfully connected to the database");
},
err => {
/** handle initial connection error */
console.log('Could not connect to the database. Exiting now...', err);
process.exit();
}
);
var port = process.env.PORT || 23804; // set our port and port must be enable on server
var router = express.Router(); // call Router methode to enable api can accept multiple routes
app.all('/*', function(req, res,next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Credentials", "true");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, X-Content-Type-Options, X-XSS-Protection, Content-Type, Accept, Key, Authorization");
res.header("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE, PATCH");
next()
});
// define a simple route
app.get('/', (req, res) => {
res.json({"message": "Welcome to Dummy application. Sign Up and Login Quicky. Organize and keep track of all forms."});
});
// Require routes
require('./app/routes/controlFile.routes.js')(app);
const server = app.listen(port, () => console.log('Dummy-App API running on port ' + port));
var fs = require('fs');
var util = require('util');
var path = __dirname + `/mylogfiles/debug(${getDate()}).log`, printNextLine = false
if(fs.existsSync(path)){
printNextLine = true
}
var log_file = fs.createWriteStream(path, {flags : 'a'});
/* 'a' : open the file for writing, positioning the stream at the end of the file. The file is created if not existing
'a+' : open the file for reading and writing, positioning the stream at the end of the file. The file is created if not existing
'r+' : open the file for reading and writing
'w+' : open the file for reading and writing, positioning the stream at the beginning of the file. The file is created if not existing
(you can find more flags at https://nodejs.org/api/fs.html#fs_file_system_flags)
*/
if(printNextLine == true){
let prnt = '***************************************************************************************************************'
log_file.write('\n' + '\n' + prnt + '\n');
}
var log_stdout = process.stdout;
console.log = function(d) { //
log_file.write((new Date).toLocaleString('en-IN', { timeZone: 'Asia/Kolkata' }) + ' | ' + util.format(d) + '\n');
log_stdout.write( util.format(d) + '\n');
};
console.error = function(d) { //
log_file.write((new Date).toLocaleString('en-IN', { timeZone: 'Asia/Kolkata' }) + ' | ' + util.format(d) + '\n');
log_stdout.write( util.format(d) + '\n');
};
process.on('uncaughtException', function (err) {
console.error(err)
// console.error((new Date).toUTCString() + ' uncaughtException:', err.message)
// console.error(err.stack)
process.exit(1)
})
process.on('SIGINT', () => {
console.info('SIGINT signal received.')
// Stops the server from accepting new connections and finishes existing connections.
server.close(function(err) {
// if error, log and exit with error (1 code)
if (err) {
console.error(err)
process.exit(1)
}
// close your database connection and exit with success (0 code)
// for example with mongoose
mongoose.connection.close(function () {
console.log('Mongoose connection disconnected')
process.exit(0)
})
})
})
function getDate(addDay){
let mydate = new Date()
var month = mydate.getMonth() + 1; // month (in integer 0-11)
var year = mydate.getFullYear(); // year
var date = mydate.getDate()
let h = mydate.getHours()
let m = mydate.getMinutes()
let s = mydate.getSeconds()
// let desiredDate = `${year}.${month}.${date} H-${h} M-${m} S-${s}`
let desiredDate = `${year}.${month}.${date}`
return desiredDate
}