Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PrismaService onModuleInit is called multiple times in NestJs

I am currently reading the documentation for a Nest.js application using Prisma. Following the documentation, I have created the following Service.

import { INestApplication, OnModuleInit } from "@nestjs/common";
import { PrismaClient } from "@prisma/client";

export class PrismaService extends PrismaClient implements OnModuleInit {
  async onModuleInit() {
    console.log('onModuleInit PrismaService')
    await this.$connect();
  }

  async enableShutdownHooks(app: INestApplication){
    this.$on('beforeExit', async () => {
      console.log('PrismaService enableShutdownHooks beforeExit')
      await app.close();
    });
  }
}

The documentation described the use of the following.

import { Module } from '@nestjs/common';
import { Prisma } from '@prisma/client';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { CsvParsersModule } from './csv-parsers/csv-parsers.module';
import { PrismaModule } from './prisma/prisma.module';
import { PrismaService } from './prisma/prisma.service';

@Module({
  imports: [CsvParsersModule],
  controllers: [AppController],
  providers: [AppService, PrismaService]
})
export class AppModule {}

However, such code will cause onModuleInit to be called repeatedly when the Service is registered elsewhere.

import { Global, Module } from '@nestjs/common';
import { CsvParsersService } from './csv-parsers.service';
import { CsvParsersController } from './csv-parsers.controller';
import { PrismaService } from 'src/prisma/prisma.service';

@Module({
  controllers: [CsvParsersController],
  providers: [CsvParsersService, PrismaService],
  exports: [CsvParsersService]
})
export class CsvParsersModule {}
[Nest] 78737  - 2022/07/21 8:05:23     LOG [NestFactory] Starting Nest application...
[Nest] 78737  - 2022/07/21 8:05:23     LOG [InstanceLoader] AppModule dependencies initialized +25ms
[Nest] 78737  - 2022/07/21 8:05:23     LOG [InstanceLoader] CsvParsersModule dependencies initialized +0ms
[Nest] 78737  - 2022/07/21 8:05:23     LOG [RoutesResolver] AppController {/}: +8ms
[Nest] 78737  - 2022/07/21 8:05:23     LOG [RouterExplorer] Mapped {/, GET} route +1ms
[Nest] 78737  - 2022/07/21 8:05:23     LOG [RoutesResolver] CsvParsersController {/csv-parsers}: +0ms
[Nest] 78737  - 2022/07/21 8:05:23     LOG [RouterExplorer] Mapped {/csv-parsers, POST} route +0ms
onModuleInit PrismaService
onModuleInit PrismaService
[Nest] 78737  - 2022/07/21 8:05:23     LOG [NestApplication] Nest application successfully started +51ms

I think the best process is for onModuleInit to be called only once. How should this be resolved?

like image 746
marsquai Avatar asked Nov 28 '25 17:11

marsquai


2 Answers

First, if you don't have, you should create a folder "prisma" or whatever and inside this folder you should insert your prisma.service.ts

import { INestApplication, OnModuleInit } from "@nestjs/common";
import { PrismaClient } from "@prisma/client";

export class PrismaService extends PrismaClient implements OnModuleInit {
  async onModuleInit() {
    console.log('onModuleInit PrismaService') // you can keep this console.log only to confirm that's right
    await this.$connect();
  }

  async enableShutdownHooks(app: INestApplication){
    this.$on('beforeExit', async () => {
      console.log('PrismaService enableShutdownHooks beforeExit')
      await app.close();
    });
  }
}

After you should create a file prisma.module.ts and insert:

import { Global, Module } from '@nestjs/common';
import { PrismaService } from './prisma.service';

@Global()
@Module({
  providers: [PrismaService],
  exports: [PrismaService],
})
export class PrismaModule {}

Now, in all modules that you need PrismaService you should remove PrismaService that is in Providers and instead add PrismaModule as import, that way:

import { Global, Module } from '@nestjs/common';
import { CsvParsersService } from './csv-parsers.service';
import { CsvParsersController } from './csv-parsers.controller';
import { PrismaModule } from 'src/prisma/prisma.module';

@Module({
  imports: [PrismaModule],
  controllers: [CsvParsersController],
  providers: [CsvParsersService],
  exports: [CsvParsersService]
})
export class CsvParsersModule {}

I had this problem and nothing was working, the key the answer is the @Global() inside module Prisma, create a module for the Prisma and import PrismaModule inside another modules.

like image 149
Leffa Avatar answered Nov 30 '25 07:11

Leffa


you registered that service twice, that's why you got two instances of the same class.

You can just add it once in some of those modules, then export it to the another one.

like image 33
Micael Levi Avatar answered Nov 30 '25 07:11

Micael Levi



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!