Graceful Shutdown with NodeJS and Terminus
Tags: node, javascript, productivity
Published: 2020-06-06 04:59:53

######*image credits [Mattias Breitholtz](https://dribbble.com/MattiasBz)* 
# What is Graceful Shutdown? 🤠
When an application is interrupted or terminated, it can be in the middle of an operation, a request or other service for example. 
Inconsistencies can happen 🤷‍♀️

Therefore, the ideal is that when an application is finished, it knows how to deal with it and finish everything in between, finish an already started request or free up resources. **This is a graceful shutdown.**

To do this, it is necessary to use the communication signals between processes of the operating system.

## What the hell are IPC (Inter-Process Communication) signals? 😥
![](https://media1.giphy.com/media/l49JD2nWqfZ7exBzW/giphy.gif?cid=ecf05e47f8ce15a1559c22c4d60ade1c3f420436b7c2c955&rid=giphy.gif)
Do you know when you use `Ctrl + C` or `kill` with a `pid` to end a program in the terminal?

Essentially this sends a signal for it to be stopped/terminated, that is, you are already sending signals to processes!

![](https://miro.medium.com/max/1400/1*-xClxdgcczhWR4fSX93KlQ.png)

Their operation is as follows: 
##### If a signal is sent to a process, the operating system will call the routine of that process to the signal, if it does not exist, it uses the default.

Example: 
##### if I use `Ctrl + C` in a program, a `SIGINT` signal is sent to it, if it has declared a function to handle this event, it will be called, if not, it will be used the default which is to interrupt the process.

## But what about NodeJS, what does it have to do with it? 🙄

Let's practice a little, in the code below are defined **3 functions** that will be called when the process receives **3 distinct signals**.
#### So far so good right?

* **SIGTERM** is the signal for termination, **code 15**.

* **SIGINT** is the signal for interruption, for example it is the one used in `Ctrl + C` and has **code 2**.

* **SIGHUP** is for reloading configuration files or terminating the terminal session, its **code is 1**.

![](https://i.imgur.com/4osHRoT.png)

This program will behave as follows: in the first three lines the functionalities will be overwritten if any of the three signals occurs, after every 6 seconds it will be written in the terminal `I am running dude`, this will be used to represent some work that the script would be doing.
Running the script above you can see the following result in the terminal after pressing `Ctrl + C` a few times on the keyboard.
```
^C
^C
I am running dude!
```
Substantially our program is receiving the signal to be interrupted using `Ctrl + C`.

  As we define another function to be called instead of the standard one (process termination), it is being called instead, and thus putting in the int console for each **SIGINT** signal.

If you haven't noticed, we have just created a process that cannot be finished, either by **SIGINT** `Ctrl + C`, **SIGTERM** or by closing the terminal **SIGHUP**. 

#### How can we kill him for good? 😟

If you want to finish the process, you will have to use the kill program. 

By default it sends a signal that cannot be heard **SIGKILL** and that ends the process regardless of what is happening.

If you try to be rascal and try to hear the **SIGKILL** signal you will receive an error, as it cannot be heard.

# Terminus 👽

It's incredible tool created by [GoDaddy
](https://github.com/godaddy) to deal with this because it adds graceful shutdown and Kubernetes readiness/liveness checks for any HTTP applications, you can even create custom error messages.

Supports some of the most popular nodejs frameworks, such as:
* express
* koa
* nodejs' core http

## Example using express
```javascript
import http from 'http'
import { createTerminus } from '@godaddy/terminus'
import { apiConfig } from '@api/config'
import { Logger } from '@api/infrastructure'
import { app } from '@api/server/application' //the express bootstrap goes here

const server = http.createServer(app)

const onSignal = () => {
  Logger.info('server is starting cleanup')
  return Promise.resolve()
}

const onShutdown = () => {
  Logger.info('cleanup finished, server is shutting down')
}

const onHealthCheck = () => Promise.resolve('UP')


const terminusConfiguration = Object.freeze({
  logger: Logger.info,
  signal: 'SIGINT',
  healthChecks: {
    '/healthcheck': onHealthCheck
  },
  onSignal,
  onShutdown
})

createTerminus(server, terminusConfiguration)

server.listen(apiConfig.port, () => Logger.info(`Magic happens on port ${apiConfig.port}`))
```
{% github https://github.com/godaddy/terminus no-readme %}
👨🏻‍💻🍻