Package Exports
- @tygra/nestjs-graceful-shutdown
- @tygra/nestjs-graceful-shutdown/build/main/index.js
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (@tygra/nestjs-graceful-shutdown) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
NestJS Graceful Shutdown 🐈
Elevate your NestJS application with seamless and reliable server shutdowns, guaranteeing uninterrupted user experiences and effortless handling of critical shutdown scenarios.
Table of Contents
- What's New
- Description
- Installation
- Example
- Configuration
- Testing Instructions
- Contact and Feedback
- License
What's New
Enhanced Reliability & Test Coverage
- Comprehensive test coverage: Achieved >99% statement coverage and >87% branch coverage with 44+ test cases
- Robust error handling: Improved fallback mechanisms and graceful degradation when termination fails
- Edge case coverage: Extensive testing of error scenarios including cleanup failures, termination errors, and signal handling
- Production-ready: Ensures your application never hangs, with intelligent fallback to direct server close
Description
Don't let your server hang indefinitely!
When you explicitly call app.close() or if the process receive a special system signal (such as SIGTERM) after correctly invoking enableShutdownHooks during application bootstrap (check out the NestJS docs), the server stops accepting new connections while maintaining existing ones. This leads to your server hanging indefinitely due to lingering keep-alive connections or unresponsive requests.
Powered by the robust @tygra/http-terminator library and backed by NestJS's built-in shutdown hooks, @tygra/nestjs-graceful-shutdown ensures graceful communication with clients currently receiving responses from your server during the shutdown process. Experience a reliable and hassle-free server shutdown with ease.
Installation
You can install the library using npm:
npm install @tygra/nestjs-graceful-shutdownNote:
@tygra/http-terminatoris automatically installed as a dependency when you install@tygra/nestjs-graceful-shutdown.
Example
To integrate @tygra/nestjs-graceful-shutdown into your NestJS application, follow these steps:
- First, import the module with
GracefulShutdownModule.forRoot(...)orGracefulShutdownModule.forRootAsync(...)into your rootAppModule. (refer to the module configuration documentation below).
import { GracefulShutdownModule } from '@tygra/nestjs-graceful-shutdown';
@Module({
imports: [GracefulShutdownModule.forRoot()],
...
})
class AppModule {}- Next, set up graceful shutdown for your NestJS application by calling the
setupGracefulShutdown(...)function.
⚠️ Warning:
@tygra/nestjs-graceful-shutdownwill automatically enable the shutdown hooks. Avoid callingenableShutdownHooksseparately in your application, as it may lead to unexpected behavior. For more information on NestJS application lifecycle, refer to the NestJS documentation.
import { setupGracefulShutdown } from '@tygra/nestjs-graceful-shutdown';
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
// Additional configuration for your NestJS app
setupGracefulShutdown({ app });
await app.listen(3000);
// Note: Timeout is used for illustration of
// delayed termination purposes only.
setTimeout(() => {
process.kill(process.pid, 'SIGTERM');
}, 5000);
}
bootstrap();Please note that the above code snippets demonstrate the basic setup of @tygra/nestjs-graceful-shutdown in your NestJS application. Make sure to adjust the code based on your specific application requirements and configuration.
Configuration
Configuration interface
The following interface is used for GracefulShutdownModule configuration:
interface IGracefulShutdownConfigOptions {
/**
* Cleanup function for releasing application resources
* during server shutdown.
*/
cleanup?: (app: INestApplication, signal?: string) => any;
/**
* The duration in milliseconds before forcefully
* terminating a connection.
* Defaults: 5000 (5 seconds).
*/
gracefulShutdownTimeout?: number;
}The following interface is used for setupGracefulShutdown function parameters:
interface ISetupFunctionParams {
/**
* Your NestJS application.
*/
app: INestApplication;
/**
* Shutdown signals that the application should listen to.
* By default, it listens to all ShutdownSignals.
*/
signals?: ShutdownSignal[] | string[];
}Zero configuration
Just import GracefulShutdownModule to AppModule:
import { GracefulShutdownModule } from '@tygra/nestjs-graceful-shutdown';
@Module({
imports: [GracefulShutdownModule.forRoot()],
...
})
class AppModule {}Synchronous configuration
Use GracefulShutdownModule.forRoot method with argument of Configuration interface:
import { GracefulShutdownModule } from '@tygra/nestjs-graceful-shutdown';
@Module({
imports: [
GracefulShutdownModule.forRoot({
cleanup: async (app, signal) => {
// releasing resources
},
gracefulShutdownTimeout:
Number(process.env.GRACEFUL_SHUTDOWN_TIMEOUT ?? 10000),
})
],
...
})
class AppModule {}Asynchronous configuration
With GracefulShutdownModule.forRootAsync you can, for example, import your ConfigModule and inject ConfigService to use it in useFactory method.
useFactory should return object with Configuration interface
Here's an example:
import { GracefulShutdownModule } from '@tygra/nestjs-graceful-shutdown';
@Injectable()
class ConfigService {
public readonly timeout = 10000;
}
@Module({
providers: [ConfigService],
exports: [ConfigService]
})
class ConfigModule {}
@Module({
imports: [
GracefulShutdownModule.forRootAsync({
imports: [ConfigModule],
inject: [ConfigService],
useFactory: async (config: ConfigService) => {
await somePromise();
return {
gracefulShutdownTimeout: config.timeout,
};
}
})
],
...
})
class AppModule {}Testing Instructions
When testing, you may need to override the graceful shutdown module with a mock module. Thanks to NestJS, this can easily be achieved using overrideModule. See the following example:
const moduleFixture: TestingModule = await Test.createTestingModule({
imports: [AppModule],
})
.overrideModule(GracefulShutdownModule)
.useModule(MockModule)
.compile();If you don't want to use a MockModule, you can use app.listen() instead of app.init() in your test file.
beforeEach(async () => {
const moduleFixture: TestingModule = await Test.createTestingModule({
imports: [AppModule],
}).compile();
app = moduleFixture.createNestApplication();
setupGracefulShutdown({ app });
await app.listen();
});Contact and Feedback
Feel free to reach out if you have any ideas, comments, or questions.
Best regards,
Hien
License
This library is licensed under the MIT License. See the LICENSE file for more details.