fix(@nestjs/core): Fix process.on memory leak bug in e2e testing

This commit is contained in:
Livio
2019-03-02 16:15:20 +01:00
committed by Livio Brunner
parent 0cc1c4ebea
commit 83ec279f85
8 changed files with 146 additions and 24 deletions

View File

@@ -1,7 +1,11 @@
import { INestApplicationContext, Logger, LoggerService } from '@nestjs/common';
import {
INestApplicationContext,
Logger,
LoggerService,
ShutdownSignal,
} from '@nestjs/common';
import { Abstract } from '@nestjs/common/interfaces';
import { Type } from '@nestjs/common/interfaces/type.interface';
import { SHUTDOWN_SIGNALS } from './constants';
import { UnknownModuleException } from './errors/exceptions/unknown-module.exception';
import {
callAppShutdownHook,
@@ -17,6 +21,7 @@ import { ModuleTokenFactory } from './injector/module-token-factory';
export class NestApplicationContext implements INestApplicationContext {
private readonly moduleTokenFactory = new ModuleTokenFactory();
private readonly containerScanner: ContainerScanner;
private readonly activeShutdownSignals: string[] = new Array<string>();
constructor(
protected readonly container: NestContainer,
@@ -60,7 +65,6 @@ export class NestApplicationContext implements INestApplicationContext {
public async init(): Promise<this> {
await this.callInitHook();
await this.callBootstrapHook();
await this.listenToShutdownSignals();
return this;
}
@@ -73,14 +77,63 @@ export class NestApplicationContext implements INestApplicationContext {
Logger.overrideLogger(logger);
}
protected listenToShutdownSignals() {
SHUTDOWN_SIGNALS.forEach((signal: any) =>
process.on(signal, async code => {
/**
* Enables the usage of shutdown hooks. Will call the
* `onApplicationShutdown` function of a provider if the
* process receives a shutdown signal.
*
* @param {ShutdownSignal[]} [signals=[]] The system signals it should listen to
*
* @returns {this} The Nest application context instance
*/
public enableShutdownHooks(signals: (ShutdownSignal | string)[] = []): this {
if (signals.length === 0) {
signals = Object.keys(ShutdownSignal).map(
(key: string) => ShutdownSignal[key],
);
} else {
// Given signals array should be unique because
// process shouldn't listen to the same signal more than once.
signals = Array.from(new Set(signals));
}
signals = signals
// To string and consistentify
.map(
(signal: ShutdownSignal | string): string =>
signal
.toString()
.toUpperCase()
.trim(),
)
// Filter out the signals which is already listening to
.filter(
(signal: string) => !this.activeShutdownSignals.includes(signal),
) as string[];
this.listenToShutdownSignals(signals);
return this;
}
/**
* Listens to shutdown signals by listening to
* process events
*
* @param {string[]} signals The system signals it should listen to
*/
protected listenToShutdownSignals(signals: string[]) {
signals.forEach((signal: string) => {
this.activeShutdownSignals.push(signal);
process.on(signal as any, async code => {
// Call the destroy and shutdown hook
// in case the process receives a shutdown signal
await this.callDestroyHook();
await this.callShutdownHook(signal);
process.exit(code || 1);
}),
);
});
});
}
/**