exit-strategy

handle uncaught exceptions with node's domains

Exit Strategy

  • Generates error event handlers to gracefully kill your app
  • Optimised for use with node's domains
  • Uses visionmedia's logger to print POSIX error codes to STDOUT that will be picked up by logwatch
var app                 = require('express').express(),
    domain              = require('domain'),
    appDomain           = domain.create(),
    exitStrategy        = require('exit-strategy'),
    exitAppDomain       = exitStrategy.app.exitAppDomain,
    exitServerDomain    = exitStrategy.server.exitServerDomain,
    exitApp             = exitAppDomain(app),
    server, exitServer;
 
// attach error handler
appDomain.on('error', exitApp);
 
// wrap app execution in domain to deal with uncaught exceptions
appDomain.run(function () {
 
    // 1. create http server
    server = server.listen(app.get('port'), function() {
        // you need to add this!
        app.set('serverListening', true);
    });
 
    // 2. replace exitApp with exitServer error handler once inited server
    exitServer = exitServerDomain(app, server);
    appDomain.on('error', exitServer).removeListener('error', exitApp);
 
    // 3. kill app for serious error evts you catch and broadcast with app.emit('seriousError')
    app.on('seriousError', exitServer);
    process.on('SIGTERM', exitServer);
 
    // 4. send 502s to new connections if started server shutdown process
    app.use(exitStrategy.middleware.closeGracefully(app));
 
    // define routes etc
});
  • by default logwatch watches all files in /var/log and subdirs
  • make sure your app logs to a file in this dir
  • logwatch will email you alerts depending upon the --detail level you set it to
  • app needs get/set methods (see getter-setter module if you don't want to use express)
  • returns error handler function (fn (err))
var app           = require('express').express(),
    appDomain     = domain.create(),
    exitAppDomain = require('exit-strategy').app.exitAppDomain(app);
 
var server = server.listen(app.get('port'), function() {
    // you need to add this!
    app.set('serverListening', true);
});
appDomain.on('error', exitServerDomain(app, server));
appDomain.run(function () {
    // run your app - set up routes etc...
});
  1. checks if the server is active
  2. calls server.close()
  3. sets timer to kill app if server.close() takes more than 30s
  4. calls exitApp
  5. calls exitProcess
  • app needs get/set methods (see getter-setter module if you don't want to use express)

  • returns error handler function (fn (err))

    var app           = require('express').express(),
        appDomain     = domain.create(),
        exitAppDomain = require('exit-strategy').app.exitAppDomain(app);
     
    appDomain.on('error', exitApp);
    appDomain.run(function () {
        // run your app
    });
  1. if app.get('serverListening') then lets serverDomain handle it
  2. sets app flag
app.set('killingApp', true);
  1. calls exitProcess
  1. logs error to STDOUT
  2. exits process
  • Middleware to prevent new connections once the exit routine has been initiated.
  • If you are load balancing then see this guide for configuring nginx to fail over to the next upstream server
var app = require('express').express(),
 
// send 502s to new connections if started server shutdown process
app.use(exitStrategy.middleware.closeGracefully(app));