Skip to content
πŸ’€ Shut down server gracefully
JavaScript
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
.github/workflows publish via github Oct 30, 2019
lib publish via github Oct 30, 2019
.editorconfig Migrated from https://github.com/omrilotan/routes Aug 22, 2019
.eslintrc Expose the sockets set Sep 3, 2019
.gitattributes
.gitignore
.mocha.js
.npmignore Migrated from https://github.com/omrilotan/routes Aug 22, 2019
.npmrc Migrated from https://github.com/omrilotan/routes Aug 22, 2019
.nvmrc
CHANGELOG.md Expose the sockets set Sep 3, 2019
README.md πŸ“– about sockets and monitoring Nov 21, 2019
app.mjs Migrated from https://github.com/omrilotan/routes Aug 22, 2019
index.js
package.json [Insert your commit message here. Be sure to make it descriptive.] Oct 2, 2019
spec.js Expose the sockets set Sep 3, 2019

README.md

@routes/graceful-shutdown

πŸ’€ Shut down server gracefully

net.Server or Express, whatever you're using should be fine

const graceful = require('@routes/graceful-shutdown');

const server = app.listen(1337); // express will return the server instance here
graceful(server);

Arguments

  • First argument is an net.Server instance (including Express server)
  • Second argument is options:
option type meaning default
timeout Number Time (in milliseconds) to wait before forcefully shutting down 10000 (10 sec)
logger Object Object with info and error functions (supports async loggers). Pass false to disable console
events Array Process events to handle ['SIGTERM', 'SIGINT']
onsuccess Function Final functionality when shutdown finished correctly process.exit(0)
onfail Function Final functionality when shutdown finished incorrectly process.exit(1)

Example of using options

graceful(server, {
	timeout: 3e4,
	logger: winston.createLogger({level: 'error'}),
});

What happens on process termination?

  1. Process termination is interrupted
  2. Open connections are instructed to end (FIN packet) and receive a new timeout to allow them to close in time
  3. The server is firing a close function
  4. After correct closing: onsuccess (default: process exists with exit code 0)
    • End correct behaviour
  5. After timeout passes - an error log is printed with the amount of connection that will be forcefully terminated
  6. onfail: (default: process exists with an exit code 1)

Add custom functionality to shutdown

Add behaviour to the graceful shut down process using a built in pub/sub mechanism

const { sub, BEFORE, AFTER } = graceful(server, {...});

// Will be triggered first thing before the procedure starts
sub(BEFORE, async() => {
	await flushThrottledThings();
	await closeDatabaseConnections();
});

// Will be triggered once the procedure has ended
sub(AFTER, () => logger.info('Okay okay, closing down'));

server.shuttingDown

After shutdown has initiated, the attribute shuttingDown is attached to server with value of true.

User can query this value on service to know not to send any more requests to the service

app.get(
	'/health',
	(request, response) => response.status(server.shuttingDown ? 503 : 200).end()
);

What else does graceful expose?

Monitor size of connections set. Should be similar open server connections

  • {Set} sockets A reference to the sockets collection
const { sockets } = graceful(server, {...});

// Monitor size of open connections every two minutes
setInterval(() => {
	stats.gauge('graceful_stored_sockets', sockets.size);

  server.getConnections((error, connections) => {
    if (error) {
      throw error;
    } else {
      stats.gauge('server_open_connections', connections);
    }
  });
}, 12e4);
You can’t perform that action at this time.