Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/omrilotan/graceful-shutdown

💀 Shut down server gracefully
https://github.com/omrilotan/graceful-shutdown

express expressjs graceful-shutdown nodejs server

Last synced: 28 days ago
JSON representation

💀 Shut down server gracefully

Awesome Lists containing this project

README

        

# @routes/graceful-shutdown [![](https://img.shields.io/badge/source--000000.svg?logo=github&style=social)](https://github.com/omrilotan/graceful-shutdown)

## 💀 Shut down server gracefully

[![](https://github.com/omrilotan/graceful-shutdown/workflows/Publish/badge.svg)](https://github.com/omrilotan/graceful-shutdown/actions) [![](https://snyk.io/test/github/omrilotan/graceful-shutdown/badge.svg)](https://snyk.io/test/github/omrilotan/graceful-shutdown) [![](https://api.codeclimate.com/v1/badges/7914da297e8693bba8f6/maintainability)](https://codeclimate.com/github/omrilotan/graceful-shutdown/maintainability)

[net.Server](https://nodejs.org/api/net.html#net_class_net_server) or [Express](https://expressjs.com/en/api.html#app.listen), whatever you're using should be fine

```js
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
```js
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
```js
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
```js
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
```js
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);
```