7

What is the best-practice for gracefully exiting a Node.js program from an external signal?

I currently use this in my code:

process.on( 'SIGINT', function() {
  console.log( "\ngracefully shutting down from  SIGINT (Crtl-C)" )
  // some other closing procedures go here
  process.exit( )
})
EhevuTov
  • 20,205
  • 16
  • 66
  • 71

2 Answers2

6

Hope this template helps. I got most of this from Simon Holmes' book Getting MEAN. Credit goes to him.

var mongoose = require( 'mongoose' );
var gracefulShutdown;
var dbURI = 'mongodb://localhost/xxx';
if (process.env.NODE_ENV === 'production') {
  dbURI = process.env.MONGOLAB_URI;
}

mongoose.connect(dbURI);

// CONNECTION EVENTS
mongoose.connection.on('connected', function () {
  console.log('Mongoose connected to ' + dbURI);
});
mongoose.connection.on('error',function (err) {
  console.log('Mongoose connection error: ' + err);
});
mongoose.connection.on('disconnected', function () {
  console.log('Mongoose disconnected');
});

// CAPTURE APP TERMINATION / RESTART EVENTS
// To be called when process is restarted or terminated
gracefulShutdown = function (msg, callback) {
  mongoose.connection.close(function () {
    console.log('Mongoose disconnected through ' + msg);
    callback();
  });
};
// For nodemon restarts
process.once('SIGUSR2', function () {
  gracefulShutdown('nodemon restart', function () {
    process.kill(process.pid, 'SIGUSR2');
  });
});
// For app termination
process.on('SIGINT', function() {
  gracefulShutdown('app termination', function () {
    process.exit(0);
  });
});
// For Heroku app termination
process.on('SIGTERM', function() {
  gracefulShutdown('Heroku app termination', function () {
    process.exit(0);
  });
});
// TODO : For Modulus app termination

// BRING IN YOUR SCHEMAS & MODELS.
require('./yyy');
Jek
  • 5,546
  • 9
  • 37
  • 67
3

It depends entirely on what your program is doing but I would say something like this:

A graceful shutdown means that any "started" I/O operations (e.g. file reads, HTTP request/responses, etc.) should complete but no new ones can be started. So your shutdown handler should prevent the possibility of starting any new operations (e.g. unbind any port listeners, prevent any new fs calls, etc.), ensure that any currently running handlers run to completion, and then exit the process.

[Edit] Of course, if your application doesn't care about the above concerns then there really isn't anything to do. When the process exits all open file/socket handles will be closed automatically so there are no problems with leaked resources.

maerics
  • 151,642
  • 46
  • 269
  • 291
  • I edited my question to something more specific concerning external signals. Thank you for your response – EhevuTov Feb 15 '12 at 18:56
  • What about things like task handlers like agenda that place their jobs on the database that persist the shutdown of the app. So when the app restarts the jobs stack? – mjwrazor Dec 21 '16 at 16:02