import { INestApplication, Injectable, Logger, OnModuleInit, } from '@nestjs/common'; import { PrismaClient } from '@prisma/client'; @Injectable() export class PrismaService extends PrismaClient implements OnModuleInit { private readonly logger = new Logger(PrismaService.name); constructor() { super({ log: [ { emit: 'stdout', level: 'query', }, { emit: 'stdout', level: 'error', }, { emit: 'stdout', level: 'info', }, { emit: 'stdout', level: 'warn', }, ], errorFormat: 'pretty', transactionOptions: { maxWait: 30 * 1000, timeout: 60 * 1000, }, }); } async onModuleInit() { this.logger.log('Try to connect database...'); const maxRetry = parseInt(process.env.PRISMA_MAX_RETRY as string) ?? 3; const retryDelay = 10000; for (let attempt = 1; attempt <= maxRetry; attempt++) { try { await this.$connect(); this.logger.log('Connected.'); return; } catch (error) { if (attempt < maxRetry) { this.logger.warn( `Connection attempt ${attempt} failed. Retrying in ${retryDelay}ms...`, ); await this.delay(retryDelay); } else { this.logger.error( `Failed to connect to the database after ${maxRetry} attempts.`, ); throw error; } } } } private delay(ms: number): Promise { return new Promise((resolve) => setTimeout(resolve, ms)); } async enableShutdownHooks(app: INestApplication) { this.$on('beforeExit' as never, async () => { this.logger.log('Wait for application closing...'); await app.close(); }); } }