В моем модуле базы данных я создаю соединение с моей базой данных. При такой настройке я получаю сообщение об ошибке

Рабочий процесс не завершился корректно, и он был принудительно завершен. Вероятно, это вызвано утечкой тестов из-за неправильного демонтажа. Попробуйте запустить --runInBand --detectOpenHandles, чтобы найти утечки.

В моих тестах e2e.

Думаю, мне нужно закрыть соединение. Но как мне запустить client.close в onModuleDestroy() в моем модуле базы данных?

database.module.ts

import { Module } from '@nestjs/common'
import { MongoClient, Db, Logger } from 'mongodb'

@Module({
    providers: [
        {
            provide: 'DATABASE_CONNECTION',
            useFactory: async (): Promise<Db> => {
                const mongo = 'mongodb://localhost:27017'
                const database = 'testing'

                try {
                    Logger.setLevel('debug')

                    const client = await MongoClient.connect(mongo, {
                        useNewUrlParser: true,
                        useUnifiedTopology: true,
                    });

                    const db = client.db(database)
                    return db
                } catch (error) {
                    throw error
                }
            }
        },
        {
            provide: 'DATABASE_CLIENT',
            useFactory: () => true // how do I get client of the above provider?
        }
    ],
    exports: ['DATABASE_CONNECTION', 'DATABASE_CLIENT']
})

export class DatabaseModule {
    constructor(
        @Inject('DATABASE_CLIENT')
        private client: Db
    ) {}

    async onModuleDestroy() {
        console.log(this.client);
        // await this.client.close()
    }
}
0
user3142695 5 Сен 2020 в 14:37

1 ответ

Лучший ответ

Открытое соединение с базой данных - частая причина этой проблемы. Модуль должен очищаться после себя, особенно это относится к тестированию, когда модуль может быть создан несколько раз.

Ссылку client необходимо сохранить для очистки. Это можно сделать с помощью одноклассного сервиса:

@Injectable()
class DatabaseConnection {
  async onModuleInit() {
    // ...same as DATABASE_CONNECTION factory
    this.client = client;
    this.db = client.db(database);
  }
  async onModuleDestroy() {
    await this.client.close()
  } 
}

Или с двумя поставщиками фабрики, один из которых хранит ссылку на client:

@Module({
  providers: [
    {
      provide: 'DATABASE_CLIENT',
      useFactory: () => ({ client: null })
    },
    {
      provide: 'DATABASE_CONNECTION',
      inject: ['DATABASE_CLIENT'],
      useFactory: async (dbClient) => {
        ...
        dbClient.client = client
        const db = client.db(database)
        return db;
      }
    }
  ]
  ...
})
export class DatabaseModule {
  constructor(@Inject('DATABASE_CLIENT') private dbClient) {}

  async onModuleDestroy() {
    await this.dbClient.client.close()
  } 
}
1
Estus Flask 5 Сен 2020 в 14:21