You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Nest.js数据库连接失败时如何触发应用优雅关闭钩子?

解决Nest.js中数据库连接失败时触发优雅关闭的问题

咱们先聊聊你当前遇到的问题:直接调用process.emit('SIGINT')没触发onApplicationShutdown,是因为Nest的优雅关闭流程需要通过框架自身的机制触发,直接发进程信号可能时机不对(比如应用还没完全初始化好),或者框架的信号处理器还没完成绑定。下面给你一套靠谱的解决方案:

1. 先确认Shutdown Hooks的启用时机

首先确保你在bootstrap里的enableShutdownHooks()是在app.listen()之前调用的,这是官方要求的正确姿势:

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.enableShutdownHooks(); // 必须在listen前启用
  await app.listen(3000);
}
bootstrap();

2. 不要在Constructor里做异步数据库检测

Constructor是同步执行的,此时Nest的依赖注入和应用初始化还没完全完成,换成OnModuleInit生命周期钩子来做数据库连接测试更稳妥:

3. 注入Nest应用实例,调用官方关闭方法

直接通过Nest提供的INestApplication实例调用close()方法,这会自动触发所有onApplicationShutdown钩子,执行你的资源释放逻辑。修改后的代码如下:

import { Injectable, OnModuleInit, Inject } from '@nestjs/common';
import { INestApplication } from '@nestjs/common';
import { createPool } from '你的数据库库';

@Injectable()
export class MyDbAccessImplementation implements OnModuleInit {
  private _pool;

  // 注入Nest应用实例
  constructor(@Inject(INestApplication) private readonly app: INestApplication) {}

  async onModuleInit() {
    this._pool = createPool(你的数据库配置);
    try {
      // 用async/await处理异步查询,比回调更清晰
      await this._pool.query(`SELECT 'test' AS TEST`);
      console.log('数据库连接成功');
    } catch (err) {
      console.error('数据库连接失败:', err);
      // 触发优雅关闭流程
      await this.app.close();
    }
  }

  // 你的其他数据库操作方法...
}

为什么之前的方法不行?

直接process.emit('SIGINT')相当于手动模拟了Ctrl+C,但如果是在应用初始化早期(比如Constructor里)执行这个操作,Nest的Shutdown Hooks可能还没完成注册,导致onApplicationShutdown没被触发。而app.close()是Nest官方提供的优雅关闭入口,会严格按照框架生命周期执行所有清理逻辑,包括调用你订阅的onApplicationShutdown方法。

内容的提问来源于stack exchange,提问作者muturgan

火山引擎 最新活动