Socket
Socket
Sign inDemoInstall

express-graceful-exit

Package Overview
Dependencies
Maintainers
2
Versions
13
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

express-graceful-exit - npm Package Compare versions

Comparing version 0.1.0 to 0.2.1

133

lib/graceful-exit.js
var _ = require('underscore')
var _ = require('underscore');
var sockets = [];
exports.middleware = function(app) {
// This flag is used to tell the middleware we create that the server wants
// to stop, so we do not allow anymore connections. This is done for all new
// connections for us by Node, but we need to handle the connections that are
// using the Keep-Alive header to stay on.
app.set('graceful_exit', false)
/**
* Keep track of open connections so we can forcibly close sockets when the suicide timeout elapses
* @param server HTTP server
*/
exports.init = function (server) {
server.on('connection', function (socket) {
sockets.push(socket);
return function(req, res, next) {
// Sorry Keep-Alive connections, but we need to part ways
if (app.settings.graceful_exit === true) {
req.connection.setTimeout(1)
}
socket.on('close', function () {
sockets.splice(sockets.indexOf(socket), 1);
});
});
};
next()
}
}
exports.gracefulExitHandler = function(app, server, _options) {
// Get the options set up
if (!_options) _options = {}
if (!_options) {
_options = {};
}
var options = _.defaults(_options, {
log : false
, logger : console.log
, suicideTimeout : 2*60*1000 + 10*1000 // 2m10s (nodejs default is 2m)
})
log : false,
logger : console.log,
suicideTimeout : 2*60*1000 + 10*1000, // 2m10s (nodejs default is 2m)
exitProcess : true,
force : false
});
var suicideTimeout;
var connectionsClosed = false;
function logger(str) {
if (options.log)
options.logger(str)
if (options.log) {
options.logger(str);
}
}
logger('Closing down the server')
function exit(code) {
if (options.exitProcess) {
process.exit(code);
} else if (options.callback) {
if (_.isFunction(options.callback)) {
options.callback(code);
} else {
logger("Registered callback is not a function");
}
}
}
if (options.callback && options.exitProcess) {
logger("Set exitProcess option to false, otherwise callback is ignored. " +
"Register a callback when process exit is handled by the caller.");
}
logger('Closing down the http server');
// Let everything know that we wish to exit gracefully
app.set('graceful_exit', true)
app.set('graceful_exit', true);

@@ -43,12 +65,15 @@ // Time to stop accepting new connections

// Everything was closed successfully, mission accomplished!
logger('All connections done, stopping process')
process.exit(0)
})
connectionsClosed = true;
clearTimeout(suicideTimeout);
logger('All connections done, stopping process');
exit(0);
});
// Disconnect all the socket.io clients
if (options.socketio) {
options.socketio.sockets.clients().forEach(function(socket) {
logger('Killing socketio socket')
socket.disconnect()
})
logger('Killing socketio socket');
socket.disconnect();
});
}

@@ -59,6 +84,42 @@

// be graceful, but failed.
setTimeout(function() {
logger('Exiting process with some open connections left')
process.exit(1)
}, options.suicideTimeout)
}
suicideTimeout = setTimeout(function() {
if (connectionsClosed) {
// this condition should never occur, see server.close() above
// user callback, if any, has already been called
if (options.exitProcess) {
process.exit(1);
}
return;
}
if (options.force) {
logger('Destroying ' + sockets.length + ' open sockets');
sockets.forEach(function (socket) {
socket.destroy();
});
} else {
logger('Exiting process before all connections are closed');
}
setTimeout(function() {
// leave a bit of time to write logs
process.exit(1);
}, 10);
}, options.suicideTimeout);
};
exports.middleware = function(app) {
// This flag is used to tell the middleware we create that the server wants
// to stop, so we do not allow anymore connections. This is done for all new
// connections for us by Node, but we need to handle the connections that are
// using the Keep-Alive header to stay on.
app.set('graceful_exit', false);
return function(req, res, next) {
// Sorry Keep-Alive connections, but we need to part ways
if (app.settings.graceful_exit === true) {
req.connection.setTimeout(1);
}
next();
};
};
{
"name": "express-graceful-exit",
"version": "0.1.0",
"description": "Allow express to support graceful exits to achieve zero downtime deploys",
"version": "0.2.1",
"description": "Allow graceful exits for express apps, supporting zero downtime deploys",
"keywords": ["express", "graceful", "exit", "shutdown", "clean", "tidy"],
"main": "index.js",

@@ -12,6 +13,9 @@ "scripts": {

"author": "Jon Keating <jon@licq.org>",
"contributors": [
"Ivo Havener <ivolucien@gmail.com>"
],
"license": "MIT",
"dependencies": {
"underscore": "~1.4.4"
"underscore": "^1.4.4"
}
}

@@ -23,7 +23,7 @@ # express-graceful-exit

```` javascript
var express = require('express')
, app = express()
, gracefulExit = require('express-graceful-exit')
var express = require('express');
var app = express();
var gracefulExit = require('express-graceful-exit');
app.use(gracefulExit.middleware(app))
app.use(gracefulExit.middleware(app));
````

@@ -39,3 +39,3 @@

if (message === 'shutdown') {
gracefulExit.gracefulExitHandler(app, server {
gracefulExit.gracefulExitHandler(app, server, {
socketio: app.settings.socketio

@@ -57,6 +57,9 @@ })

* __log:__ Shows some messages about what is going on (default false).
* __log:__ Print status messages and errors to the logger (default false).
* __logger:__ Function that accepts a string to output a log message (default console.log).
* __suicideTimeout:__ The timeout to forcefully exit the process with a return code of 1 (default 3 minutes).
* __socketio:__ An instance of socket.io, that will close all open socket.io connections (default none)
* __suicideTimeout:__ How long to wait before giving up on graceful shutdown, then returns exit code of 1 (default 2m 10s).
* __socketio:__ An instance of `socket.io`, used to close all open connections after timeout (default none)
* __exitProcess:__ If true, the module calls `process.exit()` when express has shutdown, gracefully or not (default true).
* __callback:__ Optional function that is called with the exit status code once express has shutdown, gracefully or not - use in conjunction with exitProcess=false, when the caller handles process shutdown (default none)
* __force:__ Instructs the module to forcibly close sockets once the suicide timeout elapses. Requires that `gracefulExit.init(server)` be called when initializing the HTTP server (default: false)

@@ -67,7 +70,7 @@ ## Details

1. Close the server so no new connections get accepted
2. Mark that the server will gracefully exit, so if a connection that is using the Keep-Alive header is still active, it will be told to close the connection. The HTTP status code of 502 is returned, so nginx, ELB, etc will try again with a working server.
3. If a socket.io instance is passed in the options, it enumerates all connected clients and disconnects them. The client should have code to reconnect on disconnect.
5. Once all connected clients are disconnected, the server exits with an error code of 0.
6. If there are still some remaining connections after the `suicideTimeout`, the server ungracefully exits with an error code of 1.
1. Close the http server so no new connections are accepted
2. Mark that the server will gracefully exit, so if a connection that is using the Keep-Alive header is still active, it will be told to close the connection. The HTTP status code of 502 is returned, so nginx, ELB, etc will try again with a working server
3. If a socket.io instance is passed in the options, it enumerates all connected clients and disconnects them. The client should have code to reconnect on disconnect
4. Once all connected clients are disconnected, the server exits with an error code of 0
5. If there are still some remaining connections after the `suicideTimeout`, it stops waiting and returns exit code of 1

@@ -79,2 +82,2 @@ ## Getting zero downtime deploys

#### Author: [Jon Keating](http://twitter.com/emostar)
#### Maintainer: [Ivo Havener](https://github.com/ivolucien)
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc