1- import { INestApplicationContext , Logger , LoggerService } from '@nestjs/common' ;
1+ import {
2+ INestApplicationContext ,
3+ Logger ,
4+ LoggerService ,
5+ ShutdownSignal ,
6+ } from '@nestjs/common' ;
27import { Abstract } from '@nestjs/common/interfaces' ;
38import { Type } from '@nestjs/common/interfaces/type.interface' ;
4- import { SHUTDOWN_SIGNALS } from './constants ' ;
9+ import { isEmpty } from '@nestjs/common/utils/shared.utils ' ;
510import { UnknownModuleException } from './errors/exceptions/unknown-module.exception' ;
611import {
712 callAppShutdownHook ,
@@ -17,6 +22,7 @@ import { ModuleTokenFactory } from './injector/module-token-factory';
1722export class NestApplicationContext implements INestApplicationContext {
1823 private readonly moduleTokenFactory = new ModuleTokenFactory ( ) ;
1924 private readonly containerScanner : ContainerScanner ;
25+ private readonly activeShutdownSignals : string [ ] = new Array < string > ( ) ;
2026
2127 constructor (
2228 protected readonly container : NestContainer ,
@@ -60,7 +66,6 @@ export class NestApplicationContext implements INestApplicationContext {
6066 public async init ( ) : Promise < this> {
6167 await this . callInitHook ( ) ;
6268 await this . callBootstrapHook ( ) ;
63- await this . listenToShutdownSignals ( ) ;
6469 return this ;
6570 }
6671
@@ -73,14 +78,61 @@ export class NestApplicationContext implements INestApplicationContext {
7378 Logger . overrideLogger ( logger ) ;
7479 }
7580
76- protected listenToShutdownSignals ( ) {
77- SHUTDOWN_SIGNALS . forEach ( ( signal : any ) =>
78- process . on ( signal , async code => {
81+ /**
82+ * Enables the usage of shutdown hooks. Will call the
83+ * `onApplicationShutdown` function of a provider if the
84+ * process receives a shutdown signal.
85+ *
86+ * @param {ShutdownSignal[] } [signals=[]] The system signals it should listen to
87+ *
88+ * @returns {this } The Nest application context instance
89+ */
90+ public enableShutdownHooks ( signals : ( ShutdownSignal | string ) [ ] = [ ] ) : this {
91+ if ( isEmpty ( signals ) ) {
92+ signals = Object . keys ( ShutdownSignal ) . map (
93+ ( key : string ) => ShutdownSignal [ key ] ,
94+ ) ;
95+ } else {
96+ // Given signals array should be unique because
97+ // process shouldn't listen to the same signal more than once.
98+ signals = Array . from ( new Set ( signals ) ) ;
99+ }
100+
101+ signals = signals
102+ . map ( ( signal : ShutdownSignal | string ) : string =>
103+ signal
104+ . toString ( )
105+ . toUpperCase ( )
106+ . trim ( ) ,
107+ )
108+ // Filter out the signals which is already listening to
109+ . filter (
110+ ( signal : string ) => ! this . activeShutdownSignals . includes ( signal ) ,
111+ ) as string [ ] ;
112+
113+ this . listenToShutdownSignals ( signals ) ;
114+ return this ;
115+ }
116+
117+ /**
118+ * Listens to shutdown signals by listening to
119+ * process events
120+ *
121+ * @param {string[] } signals The system signals it should listen to
122+ */
123+ protected listenToShutdownSignals ( signals : string [ ] ) {
124+ signals . forEach ( ( signal : string ) => {
125+ this . activeShutdownSignals . push ( signal ) ;
126+
127+ process . on ( signal as any , async code => {
128+ // Call the destroy and shutdown hook
129+ // in case the process receives a shutdown signal
79130 await this . callDestroyHook ( ) ;
80131 await this . callShutdownHook ( signal ) ;
132+
81133 process . exit ( code || 1 ) ;
82- } ) ,
83- ) ;
134+ } ) ;
135+ } ) ;
84136 }
85137
86138 /**
0 commit comments