You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Nest-Commander执行TypeORM数据填充时报错:连接关闭无法添加命令

问题排查:TypeORM连接关闭状态下无法创建ApplicationStatus

问题场景

数据库存在Applications表,通过TypeORM与ApplicationStatus表建立一对一关联。使用nest-commander编写命令为所有应用填充状态,命令隶属于导入到AppModule的ApplicationModule。运行命令时,获取Application数据正常,但创建ApplicationStatus时抛出错误:"Can't add new command when connection is in closed state"。

相关代码

seed-applications-status.command.ts

constructor(
    @InjectRepository(Application)
    private applicationRepository: Repository<Application>,
    private readonly applicationService: ApplicationService,
    private readonly applicationStatusService: ApplicationStatusService,
  ) {
    super();
  }

  async run(inputs: string[], options: Record<string, any>): Promise<void> {
    /* Works.. */
    const applications = await this.applicationService.findAll();
    
    /* doesn't work.. */
    applications.forEach(async (application: Application) => {
      const applicationStatus = await this.applicationStatusService.create(
        application,
      );
      application.status = applicationStatus;
      this.applicationRepository.save(application);
    });

    return;
  }

application-status.service.ts

constructor(
    @InjectRepository(ApplicationStatus)
    private readonly applicationStatusRepository: Repository<ApplicationStatus>,
  ) {}

  async create(application: Application) {
    const applicationStatus = this.applicationStatusRepository.create({
      status: 'PENDING',
      cnieStatus: 'PENDING',
      schoolCertificateStatus: 'PENDING',
      regulationsStatus: 'PENDING',
      gradesStatus: 'PENDING',
    });
    applicationStatus.application = application;
    await this.applicationStatusRepository.save(applicationStatus);

    return applicationStatus;
  }

main-cli.ts

async function bootstrap() {
  await CommandFactory.run(AppModule, {
    logger: ['warn', 'error'],
  });
}
bootstrap();

问题原因

核心问题在于run方法中使用了forEach遍历异步操作,forEach不会等待内部的异步任务完成。当所有forEach循环结束后,run方法直接返回,nest-commander认为命令执行完毕,会立即关闭数据库连接。但此时forEach内部的create和save异步操作还在后台执行,导致在已关闭的连接上执行数据库命令,抛出连接关闭的错误。

解决方案

方案1:顺序执行异步任务(for...of)

将forEach替换为for...of循环,确保所有异步操作按顺序执行完毕后,run方法才返回,避免连接提前关闭:

async run(inputs: string[], options: Record<string, any>): Promise<void> {
  const applications = await this.applicationService.findAll();
  
  // 使用for...of替代forEach,等待每个异步操作完成
  for (const application of applications) {
    const applicationStatus = await this.applicationStatusService.create(application);
    application.status = applicationStatus;
    await this.applicationRepository.save(application); // 等待保存操作完成
  }

  return;
}

方案2:并行执行异步任务(Promise.all)

如果希望提升执行效率,可使用Promise.all并行处理所有异步任务,等待全部完成后再结束命令:

async run(inputs: string[], options: Record<string, any>): Promise<void> {
  const applications = await this.applicationService.findAll();
  
  // 收集所有异步任务,并行执行并等待全部完成
  await Promise.all(applications.map(async (application) => {
    const applicationStatus = await this.applicationStatusService.create(application);
    application.status = applicationStatus;
    return this.applicationRepository.save(application);
  }));

  return;
}

内容的提问来源于stack exchange,提问作者Achraf El Khamsi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 17:23:16