fix(backend): resolve database connection leak in infra-config operations (#5825)

This commit is contained in:
Mir Arif Hasan 2026-02-04 17:55:00 +06:00 committed by GitHub
parent 2dc3463b69
commit 37e9207b43
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 35 additions and 8 deletions

View file

@ -16,6 +16,29 @@ type DefaultInfraConfig = {
isEncrypted: boolean;
};
// Singleton PrismaService instance for infra config operations
let sharedPrismaInstance: PrismaService | null = null;
/**
* Get or create a shared PrismaService instance for infra config operations
*/
function getSharedPrismaInstance(): PrismaService {
if (!sharedPrismaInstance) {
sharedPrismaInstance = new PrismaService();
}
return sharedPrismaInstance;
}
/**
* Disconnect the shared Prisma instance during application shutdown
*/
export async function disconnectSharedPrismaInstance(): Promise<void> {
if (sharedPrismaInstance) {
await sharedPrismaInstance.onModuleDestroy();
sharedPrismaInstance = null;
}
}
/**
* Returns a mapping of authentication providers to their required configuration keys based on the current environment configuration.
*/
@ -67,8 +90,8 @@ export function getAuthProviderRequiredKeys(
* (ConfigModule will set the environment variables in the process)
*/
export async function loadInfraConfiguration() {
const prisma = getSharedPrismaInstance();
try {
const prisma = new PrismaService();
const infraConfigs = await prisma.infraConfig.findMany();
const environmentObject: Record<string, string> = {};
@ -97,7 +120,7 @@ export async function loadInfraConfiguration() {
* @returns Array of default infra configs
*/
export async function getDefaultInfraConfigs(): Promise<DefaultInfraConfig[]> {
const prisma = new PrismaService();
const prisma = getSharedPrismaInstance();
// Prepare rows for 'infra_config' table with default values (from .env) for each 'name'
const onboardingCompleteStatus = await isOnboardingCompleted();
@ -324,7 +347,7 @@ export async function getDefaultInfraConfigs(): Promise<DefaultInfraConfig[]> {
export async function getMissingInfraConfigEntries(
infraConfigDefaultObjs: DefaultInfraConfig[],
) {
const prisma = new PrismaService();
const prisma = getSharedPrismaInstance();
const dbInfraConfigs = await prisma.infraConfig.findMany();
const missingEntries = infraConfigDefaultObjs.filter(
@ -342,7 +365,7 @@ export async function getMissingInfraConfigEntries(
export async function getEncryptionRequiredInfraConfigEntries(
infraConfigDefaultObjs: DefaultInfraConfig[],
) {
const prisma = new PrismaService();
const prisma = getSharedPrismaInstance();
const dbInfraConfigs = await prisma.infraConfig.findMany();
const requiredEncryption = dbInfraConfigs.filter((dbConfig) => {
@ -400,7 +423,7 @@ export function stopApp() {
* @returns Array of configured SSO providers
*/
export async function getConfiguredSSOProvidersFromInfraConfig() {
const prisma = new PrismaService();
const prisma = getSharedPrismaInstance();
const env = await loadInfraConfiguration();
const providerConfigKeys = getAuthProviderRequiredKeys(env);
@ -437,7 +460,7 @@ export async function getConfiguredSSOProvidersFromInfraConfig() {
* @returns boolean
*/
export async function isOnboardingCompleted(): Promise<boolean> {
const prisma = new PrismaService();
const prisma = getSharedPrismaInstance();
const allowedProviders = await prisma.infraConfig.findUnique({
where: { name: InfraConfigEnum.VITE_ALLOWED_AUTH_PROVIDERS },
select: { value: true },

View file

@ -1,4 +1,4 @@
import { Injectable, OnModuleInit } from '@nestjs/common';
import { Injectable, OnModuleDestroy, OnModuleInit } from '@nestjs/common';
import { InfraConfig } from './infra-config.model';
import { PrismaService } from 'src/prisma/prisma.service';
import { InfraConfig as DBInfraConfig } from 'src/generated/prisma/client';
@ -26,6 +26,7 @@ import { ConfigService } from '@nestjs/config';
import {
ServiceStatus,
buildDerivedEnv,
disconnectSharedPrismaInstance,
getDefaultInfraConfigs,
getEncryptionRequiredInfraConfigEntries,
getMissingInfraConfigEntries,
@ -45,7 +46,7 @@ import * as crypto from 'crypto';
import { PrismaError } from 'src/prisma/prisma-error-codes';
@Injectable()
export class InfraConfigService implements OnModuleInit {
export class InfraConfigService implements OnModuleInit, OnModuleDestroy {
constructor(
private readonly prisma: PrismaService,
private readonly configService: ConfigService,
@ -72,6 +73,9 @@ export class InfraConfigService implements OnModuleInit {
async onModuleInit() {
await this.initializeInfraConfigTable();
}
async onModuleDestroy() {
await disconnectSharedPrismaInstance();
}
/**
* Initialize the 'infra_config' table with values from .env