【问题标题】:Gracefully closing connection of DB using TypeORM in NestJs在 NestJs 中使用 TypeORM 优雅地关闭 DB 连接
【发布时间】:2022-01-10 14:38:55
【问题描述】:

所以,在我深入探讨这个问题之前,让我向您解释一下我的应用的基本原理。

我在我的应用中连接到 DB(TypeOrm)、Kafka(kafkajs)

我的应用是 1 个主题的消费者,其中:

  1. 在回调处理程序中获取一些数据,并使用 TypeORM 实体将该数据放入一个表中
  2. 维护 全局地图(在某个类的一些单例实例中)和一些 id(我在点 1 的数据中得到)。

应用关闭时,我的任务是:

  1. 从 Kafka 断开所有主题(此服务连接到)的消费者
  2. 遍历全球地图(第 2 点)并在某个主题中重新放置消息
  3. 使用 close 方法断开数据库连接

这里有一些代码可以帮助你理解我是如何在 NestJs 中的 Server 上添加生命周期事件的。

system.server.life.cycle.events.ts

@Injectable()
export class SystemServerLifeCycleEventsShared implements BeforeApplicationShutdown {
    constructor(@Inject(WINSTON_MODULE_PROVIDER) private readonly logger: Logger, private readonly someService: SomeService) {}

    async beforeApplicationShutdown(signal: string) {
        const [err] = await this.someService.handleAbruptEnding();

        if (err) this.logger.info(`beforeApplicationShutdown, error::: ${JSON.stringify(err)}`);
        this.logger.info(`beforeApplicationShutdown, signal ${signal}`);
    }
}

some.service.ts

export class SomeService {
    constructor(private readonly kafkaConnector: KafkaConnector, private readonly postgresConnector: PostgresConnector) {}
    
    public async handleAbruptEnding(): Promise<any> {
        
        await this.kafkaConnector.disconnectAllConsumers();
        for(READ_FROM_GLOBAL_STORE) { 
             await this.kafkaConnector.function.call.to.repark.the.message();
        }
        
        await this.postgresConnector.disconnectAllConnections();

        return true;
    }
}

postgres.connector.ts

export class PostgresConnector {
    private connectionManager: ConnectionManager; 
    constructor () {
        this.connectionManager = getConnectionManager();
    }

    public async disconnectAllConnections(): Promise<void[]> {
        const connectionClosePromises: Promise<void> = [];
        connectionManager.connections?.forEach((connection) => {
            if (connection.isConnected) connectionClosePromises.push(connection.close());
        });

        return Promise.all(connectionClosePromises);
    }
}

ConnectionManager&getConnectionManager() 从 TypeORM 模块导入。

下面是我面临的一些不寻常的异常/行为:

  1. 断开所有连接会引发异常/错误,如引用:

    错误 [TypeOrmModule] 无法在“默认”连接上执行操作,因为连接尚未建立。 如果连接还没有建立,那么我的 isConnected 怎么会在 if 中实现。我在任何地方都没有任何线索,这怎么可能。以及如何在 TypeORM 中优雅地关闭连接。

  2. 我们真的需要在 TypeORM 中处理连接的关闭还是它在内部处理它。

  3. 即使 TypeORM 在内部处理连接闭包,我们如何显式实现它。

  4. 如果连接正确断开,是否可以触发任何回调,以便我确定断开连接实际上是从数据库发生的。

  5. 在我按下 CTRL + C(模仿我的服务器进程的突然/关闭)并且控制权返回到终端之后,一些消息会出现。这意味着,在句柄返回到我的终端后,一些线程正在返回(????,不知道,我将如何处理这个,因为如果你看到,我的 handleAbruptHandling 是 awaited 而且,我交叉检查所有承诺都在正确等待。)

需要了解的一些事情:

  1. 我正确添加了我的模块来创建服务器生命周期事件的挂钩。
  2. 正确注入了几乎所有类中的对象。
  3. 没有从 NEST 得到任何 DI 问题并且服务器正在正常启动。

请说明一下,让我知道如何在 NestJs 中使用 typeorm api 优雅地断开与数据库的连接,以防突然关闭。

在此先感谢,祝您编码愉快:)

【问题讨论】:

    标签: exception nestjs typeorm


    【解决方案1】:

    晚了一点,但可能对某人有所帮助..

    您在TypeOrmModuleOptions 中缺少参数 keepConnectionAlivetrue,typeOrm 默认情况下不会保持连接处于活动状态。我将 keepConnectionAlive 设置为 false,如果事务保持连接打开,我将关闭连接(typeorm 等到事务或其他进程完成后再关闭连接),这是我的实现

    import { Logger, Injectable, OnApplicationShutdown } from '@nestjs/common';
    import { getConnectionManager } from 'typeorm';
    
    @Injectable()
    export class LifecyclesService implements OnApplicationShutdown {
      private readonly logger = new Logger();
    
      onApplicationShutdown(signal: string) {
        this.logger.warn('SIGNTERM: ', signal);
        this.closeDBConnection();
      }
    
      closeDBConnection() {
        const conn = getConnectionManager().get();
    
        if (conn.isConnected) {
          conn
            .close()
            .then(() => {
              this.logger.log('DB conn closed');
            })
            .catch((err: any) => {
              this.logger.error('Error clossing conn to DB, ', err);
            });
        } else {
          this.logger.log('DB conn already closed.');
        }
      }
    }
    

    【讨论】:

      猜你喜欢
      • 2021-06-03
      • 2015-06-25
      • 1970-01-01
      • 2012-10-29
      • 2012-04-05
      • 2019-06-27
      • 1970-01-01
      • 2011-08-07
      • 2020-12-20
      相关资源
      最近更新 更多