fix(backend): resolve database connection leak in infra-config operations (#5825)
This commit is contained in:
parent
2dc3463b69
commit
37e9207b43
2 changed files with 35 additions and 8 deletions
|
|
@ -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 },
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in a new issue