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' ;
59import { UnknownModuleException } from './errors/exceptions/unknown-module.exception' ;
610import {
711 callAppShutdownHook ,
@@ -17,6 +21,7 @@ import { ModuleTokenFactory } from './injector/module-token-factory';
1721export class NestApplicationContext implements INestApplicationContext {
1822 private readonly moduleTokenFactory = new ModuleTokenFactory ( ) ;
1923 private readonly containerScanner : ContainerScanner ;
24+ private readonly activeShutdownSignals : string [ ] = new Array < string > ( ) ;
2025
2126 constructor (
2227 protected readonly container : NestContainer ,
@@ -60,7 +65,6 @@ export class NestApplicationContext implements INestApplicationContext {
6065 public async init ( ) : Promise < this> {
6166 await this . callInitHook ( ) ;
6267 await this . callBootstrapHook ( ) ;
63- await this . listenToShutdownSignals ( ) ;
6468 return this ;
6569 }
6670
@@ -73,14 +77,63 @@ export class NestApplicationContext implements INestApplicationContext {
7377 Logger . overrideLogger ( logger ) ;
7478 }
7579
76- protected listenToShutdownSignals ( ) {
77- SHUTDOWN_SIGNALS . forEach ( ( signal : any ) =>
78- process . on ( signal , async code => {
80+ /**
81+ * Enables the usage of shutdown hooks. Will call the
82+ * `onApplicationShutdown` function of a provider if the
83+ * process receives a shutdown signal.
84+ *
85+ * @param {ShutdownSignal[] } [signals=[]] The system signals it should listen to
86+ *
87+ * @returns {this } The Nest application context instance
88+ */
89+ public enableShutdownHooks ( signals : ( ShutdownSignal | string ) [ ] = [ ] ) : this {
90+ if ( signals . length === 0 ) {
91+ signals = Object . keys ( ShutdownSignal ) . map (
92+ ( key : string ) => ShutdownSignal [ key ] ,
93+ ) ;
94+ } else {
95+ // Given signals array should be unique because
96+ // process shouldn't listen to the same signal more than once.
97+ signals = Array . from ( new Set ( signals ) ) ;
98+ }
99+
100+ signals = signals
101+ // To string and consistentify
102+ . map (
103+ ( signal : ShutdownSignal | string ) : string =>
104+ signal
105+ . toString ( )
106+ . toUpperCase ( )
107+ . trim ( ) ,
108+ )
109+ // Filter out the signals which is already listening to
110+ . filter (
111+ ( signal : string ) => ! this . activeShutdownSignals . includes ( signal ) ,
112+ ) as string [ ] ;
113+
114+ this . listenToShutdownSignals ( signals ) ;
115+ return this ;
116+ }
117+
118+ /**
119+ * Listens to shutdown signals by listening to
120+ * process events
121+ *
122+ * @param {string[] } signals The system signals it should listen to
123+ */
124+ protected listenToShutdownSignals ( signals : string [ ] ) {
125+ signals . forEach ( ( signal : string ) => {
126+ this . activeShutdownSignals . push ( signal ) ;
127+
128+ process . on ( signal as any , async code => {
129+ // Call the destroy and shutdown hook
130+ // in case the process receives a shutdown signal
79131 await this . callDestroyHook ( ) ;
80132 await this . callShutdownHook ( signal ) ;
133+
81134 process . exit ( code || 1 ) ;
82- } ) ,
83- ) ;
135+ } ) ;
136+ } ) ;
84137 }
85138
86139 /**
0 commit comments