1 | import { LogFn } from 'pino'
|
2 | import defaultLogger from './logger'
|
3 |
|
4 | export default function registerGracefulShutdown(
|
5 | this: any,
|
6 | closeHandlers: Array<() => Promise<any>> = [],
|
7 | {
|
8 | logger = {
|
9 | info: defaultLogger.info.bind(defaultLogger) as LogFn,
|
10 | error: defaultLogger.error.bind(defaultLogger) as LogFn,
|
11 | },
|
12 | timeout = 30,
|
13 | } = {}
|
14 | ) {
|
15 |
|
16 | process.once('SIGTERM', gracefulShutDown.bind(this, 'SIGTERM'))
|
17 | process.once('SIGINT', gracefulShutDown.bind(this, 'SIGINT'))
|
18 |
|
19 | async function gracefulShutDown(signal = 'SIGTERM') {
|
20 | logger.info(`got kill signal (${signal}), starting graceful shut down`)
|
21 |
|
22 |
|
23 | if (timeout) {
|
24 | setTimeout(() => {
|
25 | logger.error('could not finish in time, forcefully exiting')
|
26 | process.exit(1)
|
27 | }, timeout * 1000).unref()
|
28 | }
|
29 |
|
30 |
|
31 | let isError = false
|
32 | for (const handler of closeHandlers) {
|
33 | try {
|
34 | await Promise.resolve(handler())
|
35 | } catch (err) {
|
36 | logger.error(err, 'error happened during graceful shut down')
|
37 | isError = true
|
38 | }
|
39 | }
|
40 |
|
41 | if (isError) {
|
42 | process.exit(1)
|
43 | }
|
44 |
|
45 | logger.info('graceful shut down finished')
|
46 | process.kill(process.pid, signal)
|
47 | }
|
48 | }
|