Skip to content

πŸ’€ Shut down server gracefully

Notifications You must be signed in to change notification settings

omrilotan/graceful-shutdown

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

17 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

@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);