From b6cb5831c2b5f30e596cd286db6ebadb807965f6 Mon Sep 17 00:00:00 2001 From: paritosh18 Date: Tue, 9 Dec 2025 13:49:20 +0530 Subject: [PATCH] Refactor Prisma client usage and enhance service integration for improved connection management --- layers/prisma/nodejs/package.json | 5 ++-- prisma/prisma.ts | 6 ++-- serverless.yml | 14 ++++++---- src/common/database/prisma.client.ts | 28 +++++++++++++++---- src/common/database/prisma.lambda.service.ts | 23 ++------------- src/common/database/prisma.service.ts | 7 +++++ .../services/amNotification.service.ts | 4 +-- 7 files changed, 49 insertions(+), 38 deletions(-) diff --git a/layers/prisma/nodejs/package.json b/layers/prisma/nodejs/package.json index 47d0046..5cd95ff 100644 --- a/layers/prisma/nodejs/package.json +++ b/layers/prisma/nodejs/package.json @@ -1,10 +1,11 @@ { "name": "prisma-layer", "version": "1.0.0", - "description": "Lambda layer for Prisma 7 with pg driver adapter", + "description": "Lambda layer for Prisma 7 with pg driver adapter and zod", "dependencies": { "@prisma/client": "^7.0.1", "@prisma/adapter-pg": "^7.0.1", - "pg": "^8.13.0" + "pg": "^8.13.0", + "zod": "^4.1.12" } } diff --git a/prisma/prisma.ts b/prisma/prisma.ts index 61913bb..966c5cd 100644 --- a/prisma/prisma.ts +++ b/prisma/prisma.ts @@ -1,8 +1,8 @@ // prisma.ts -import { PrismaClient } from '@prisma/client'; +// Re-export from the main singleton for consistency +import { prisma } from '../src/common/database/prisma.client'; -// The DATABASE_URL environment variable will be automatically used -export const prisma = new PrismaClient(); +export { prisma }; process.on('SIGINT', async () => { await prisma.$disconnect(); diff --git a/serverless.yml b/serverless.yml index f776226..d4210bc 100644 --- a/serverless.yml +++ b/serverless.yml @@ -82,11 +82,12 @@ build: platform: node # Mark as external so they're not bundled into the JS external: - # - '@prisma/client' - # - '.prisma/client' - # - '.prisma' + - '@prisma/client' + - '.prisma/client' + - '.prisma' - '@prisma/adapter-pg' - 'pg' + - 'zod' - '@aws-sdk/*' - '@smithy/*' - '@aws-crypto/*' @@ -97,10 +98,11 @@ build: - '@smithy/*' - '@aws-crypto/*' - '@prisma/adapter-pg' - # - '@prisma/client' - # - '.prisma' - # - '.prisma/client' + - '@prisma/client' + - '.prisma' + - '.prisma/client' - 'pg' + - 'zod' - 'pg-*' - 'postgres-*' - 'pgpass' diff --git a/src/common/database/prisma.client.ts b/src/common/database/prisma.client.ts index 1da7d2e..1831f66 100644 --- a/src/common/database/prisma.client.ts +++ b/src/common/database/prisma.client.ts @@ -1,11 +1,29 @@ import { PrismaClient } from '@prisma/client'; import { PrismaPg } from '@prisma/adapter-pg'; -const adapter = new PrismaPg({ connectionString: process.env.DATABASE_URL }); +// Singleton pattern for Prisma client - prevents "Too many database connections" error +const globalForPrisma = globalThis as unknown as { + prisma: PrismaClient | undefined; +}; -export const prisma = new PrismaClient({ - adapter, - log: process.env.NODE_ENV === 'dev' ? ['query', 'info', 'warn', 'error'] : ['error'], -}); +function createPrismaClient() { + const adapter = new PrismaPg({ connectionString: process.env.DATABASE_URL }); + + return new PrismaClient({ + adapter, + log: process.env.NODE_ENV === 'dev' ? ['query', 'info', 'warn', 'error'] : ['error'], + }); +} + +export const prisma = globalForPrisma.prisma ?? createPrismaClient(); + +if (process.env.NODE_ENV !== 'production') { + globalForPrisma.prisma = prisma; +} + +// For serverless environments, always cache the client +if (process.env.IS_OFFLINE || process.env.AWS_LAMBDA_FUNCTION_NAME) { + globalForPrisma.prisma = prisma; +} diff --git a/src/common/database/prisma.lambda.service.ts b/src/common/database/prisma.lambda.service.ts index 0aa5b78..e5409b6 100644 --- a/src/common/database/prisma.lambda.service.ts +++ b/src/common/database/prisma.lambda.service.ts @@ -1,22 +1,5 @@ -import { PrismaClient } from '@prisma/client'; -import { PrismaPg } from '@prisma/adapter-pg'; - -const adapter = new PrismaPg({ - connectionString: process.env.DATABASE_URL!, -}); - -let prisma: PrismaClient; - -if (!(global as any).prisma) { - (global as any).prisma = new PrismaClient({ - adapter, - log: - process.env.NODE_ENV === 'dev' - ? ['query', 'info', 'warn', 'error'] - : ['error'], - }); -} - -prisma = (global as any).prisma; +// Re-export the singleton prisma client for Lambda handlers +// This ensures all Lambda functions use the same cached connection +import { prisma } from './prisma.client'; export const prismaClient = prisma; \ No newline at end of file diff --git a/src/common/database/prisma.service.ts b/src/common/database/prisma.service.ts index bb6565f..b75245f 100644 --- a/src/common/database/prisma.service.ts +++ b/src/common/database/prisma.service.ts @@ -1,8 +1,15 @@ import { Injectable, OnModuleInit, OnModuleDestroy } from '@nestjs/common'; import { PrismaClient } from '@prisma/client'; +import { prisma } from './prisma.client'; @Injectable() export class PrismaService extends PrismaClient implements OnModuleInit, OnModuleDestroy { + constructor() { + super(); + // Use the singleton instance + Object.assign(this, prisma); + } + async onModuleInit() { await this.$connect(); } diff --git a/src/modules/minglaradmin/services/amNotification.service.ts b/src/modules/minglaradmin/services/amNotification.service.ts index d38bf39..2990159 100644 --- a/src/modules/minglaradmin/services/amNotification.service.ts +++ b/src/modules/minglaradmin/services/amNotification.service.ts @@ -1,10 +1,10 @@ import { Injectable } from '@nestjs/common'; -import { PrismaService } from '../../../common/database/prisma.lambda.service'; +import { prismaClient } from '../../../common/database/prisma.lambda.service'; import { sendAMEmailForHostAssign } from './AMEmail.service'; @Injectable() export class AMNotificationService { - constructor(private prisma: PrismaService) {} + private prisma = prismaClient; /** * Fetch account manager email by id and send assignment email.