From 71729813a9079a89ceb7488639b53a472f91b367 Mon Sep 17 00:00:00 2001 From: "cal.com" Date: Fri, 9 Jan 2026 17:59:10 +0200 Subject: [PATCH] Revert "chore: USE_POOL env var for api v2 prisma pooling" This reverts commit a97092619f5cdbe4940e2bdfe26e20f3a13e7fc1. --- apps/api/v2/src/bootstrap.ts | 1 + apps/api/v2/src/config/app.ts | 2 +- apps/api/v2/src/config/type.ts | 1 - apps/api/v2/src/env.ts | 3 +- apps/api/v2/src/main.ts | 4 ++ .../src/modules/prisma/prisma-read.service.ts | 63 ++++++++----------- .../modules/prisma/prisma-worker.module.ts | 8 +-- .../modules/prisma/prisma-write.service.ts | 49 ++++++--------- .../v2/src/modules/prisma/prisma.module.ts | 8 +-- .../v2/src/swagger/generate-swagger-script.ts | 1 + biome.json | 24 +++---- 11 files changed, 71 insertions(+), 93 deletions(-) diff --git a/apps/api/v2/src/bootstrap.ts b/apps/api/v2/src/bootstrap.ts index 22a2139804..a7bc78c9a2 100644 --- a/apps/api/v2/src/bootstrap.ts +++ b/apps/api/v2/src/bootstrap.ts @@ -1,5 +1,6 @@ import "./instrument"; +import process from "node:process"; import { API_VERSIONS, API_VERSIONS_ENUM, diff --git a/apps/api/v2/src/config/app.ts b/apps/api/v2/src/config/app.ts index 4a951ee4fe..a32a7d5854 100644 --- a/apps/api/v2/src/config/app.ts +++ b/apps/api/v2/src/config/app.ts @@ -1,4 +1,5 @@ import { getEnv } from "@/env"; + import type { AppConfig } from "./type"; const loadConfig = (): AppConfig => { @@ -30,7 +31,6 @@ const loadConfig = (): AppConfig => { workerReadPoolMax: getEnv("DATABASE_READ_WORKER_POOL_MAX", 4), workerWritePoolMax: getEnv("DATABASE_WRITE_WORKER_POOL_MAX", 6), redisUrl: getEnv("REDIS_URL"), - usePool: getEnv("USE_POOL", "true") === "true", }, next: { authSecret: getEnv("NEXTAUTH_SECRET"), diff --git a/apps/api/v2/src/config/type.ts b/apps/api/v2/src/config/type.ts index f3ee7ebe6f..0b6cd7d0c0 100644 --- a/apps/api/v2/src/config/type.ts +++ b/apps/api/v2/src/config/type.ts @@ -18,7 +18,6 @@ export type AppConfig = { workerReadPoolMax: number; workerWritePoolMax: number; redisUrl: string; - usePool: boolean; }; next: { authSecret: string; diff --git a/apps/api/v2/src/env.ts b/apps/api/v2/src/env.ts index 5d6b8f27c2..c25a9cd480 100644 --- a/apps/api/v2/src/env.ts +++ b/apps/api/v2/src/env.ts @@ -40,10 +40,11 @@ export type Environment = { DATABASE_WRITE_WORKER_POOL_MAX: number; ENABLE_SLOTS_WORKERS: string; SLOTS_WORKER_POOL_SIZE: string; - USE_POOL: string; }; export const getEnv = (key: K, fallback?: Environment[K]): Environment[K] => { + // biome-ignore lint/style/noProcessEnv: + // biome-ignore lint/correctness/noProcessGlobal: const value = process.env[key] as Environment[K] | undefined; if (value === undefined) { diff --git a/apps/api/v2/src/main.ts b/apps/api/v2/src/main.ts index db8400facf..144733438d 100644 --- a/apps/api/v2/src/main.ts +++ b/apps/api/v2/src/main.ts @@ -1,13 +1,17 @@ import "dotenv/config"; import { IncomingMessage, Server, ServerResponse } from "node:http"; +import process from "node:process"; import { Logger } from "@nestjs/common"; import { ConfigService } from "@nestjs/config"; import { NestFactory } from "@nestjs/core"; import type { NestExpressApplication } from "@nestjs/platform-express"; + import { WinstonModule } from "nest-winston"; import * as qs from "qs"; + import type { AppConfig } from "@/config/type"; + import { AppModule } from "./app.module"; import { bootstrap } from "./bootstrap"; import { loggerConfig } from "./lib/logger"; diff --git a/apps/api/v2/src/modules/prisma/prisma-read.service.ts b/apps/api/v2/src/modules/prisma/prisma-read.service.ts index ca28e9c049..07722c5c89 100644 --- a/apps/api/v2/src/modules/prisma/prisma-read.service.ts +++ b/apps/api/v2/src/modules/prisma/prisma-read.service.ts @@ -1,66 +1,63 @@ -import { PrismaClient } from "@calcom/prisma/client"; -import { Injectable, Logger, type OnModuleDestroy, type OnModuleInit } from "@nestjs/common"; +import type { OnModuleDestroy, OnModuleInit } from "@nestjs/common"; +import { Injectable, Logger } from "@nestjs/common"; import { ConfigService } from "@nestjs/config"; import { PrismaPg } from "@prisma/adapter-pg"; import { Pool } from "pg"; +import { PrismaClient } from "@calcom/prisma/client"; + const DB_MAX_POOL_CONNECTION = 10; +export interface PrismaServiceOptions { + readUrl?: string; + maxReadConnections?: number; + e2e?: boolean; + type: "main" | "worker"; +} + @Injectable() export class PrismaReadService implements OnModuleInit, OnModuleDestroy { private logger = new Logger("PrismaReadService"); public prisma!: PrismaClient; private pool!: Pool; + private options!: PrismaServiceOptions; - constructor(configService?: ConfigService) { + constructor(private configService?: ConfigService) { if (configService) { // Use ConfigService defaults const readUrl = configService.get("db.readUrl", { infer: true }); const poolMax = parseInt( - configService.get("db.readPoolMax", { infer: true }) ?? DB_MAX_POOL_CONNECTION, - 10 + configService.get("db.readPoolMax", { infer: true }) ?? DB_MAX_POOL_CONNECTION ); const e2e = configService.get("e2e", { infer: true }) ?? false; - const usePool = configService.get("db.usePool", { infer: true }) ?? true; this.setOptions({ readUrl, maxReadConnections: poolMax, e2e, - usePool, type: "main", }); } } - setOptions(options: PrismaServiceOptions): void { + setOptions(options: PrismaServiceOptions) { + this.options = options; + const dbUrl = options.readUrl; const isE2E = options.e2e ?? false; - const usePool = options.usePool ?? true; - if (usePool) { - let maxReadConnections = options.maxReadConnections ?? DB_MAX_POOL_CONNECTION; - if (isE2E) { - maxReadConnections = 1; - } + this.pool = new Pool({ + connectionString: dbUrl, + max: isE2E ? 1 : options.maxReadConnections ?? DB_MAX_POOL_CONNECTION, + idleTimeoutMillis: 300000, + }); - this.pool = new Pool({ - connectionString: dbUrl, - max: maxReadConnections, - idleTimeoutMillis: 300000, - }); - - const adapter = new PrismaPg(this.pool); - this.prisma = new PrismaClient({ adapter }); - } else { - this.prisma = new PrismaClient({ - datasourceUrl: dbUrl, - }); - } + const adapter = new PrismaPg(this.pool); + this.prisma = new PrismaClient({ adapter }); } - async onModuleInit(): Promise { + async onModuleInit() { if (!this.prisma) return; try { @@ -71,7 +68,7 @@ export class PrismaReadService implements OnModuleInit, OnModuleDestroy { } } - async onModuleDestroy(): Promise { + async onModuleDestroy() { try { if (this.prisma) await this.prisma.$disconnect(); if (this.pool) await this.pool.end(); @@ -80,11 +77,3 @@ export class PrismaReadService implements OnModuleInit, OnModuleDestroy { } } } - -export interface PrismaServiceOptions { - readUrl?: string; - maxReadConnections?: number; - e2e?: boolean; - usePool?: boolean; - type: "main" | "worker"; -} diff --git a/apps/api/v2/src/modules/prisma/prisma-worker.module.ts b/apps/api/v2/src/modules/prisma/prisma-worker.module.ts index d4a04f05c4..4a84620e60 100644 --- a/apps/api/v2/src/modules/prisma/prisma-worker.module.ts +++ b/apps/api/v2/src/modules/prisma/prisma-worker.module.ts @@ -1,7 +1,7 @@ -import { Module } from "@nestjs/common"; -import { ConfigModule, ConfigService } from "@nestjs/config"; import { PrismaReadService } from "@/modules/prisma/prisma-read.service"; import { PrismaWriteService } from "@/modules/prisma/prisma-write.service"; +import { Module } from "@nestjs/common"; +import { ConfigModule, ConfigService } from "@nestjs/config"; @Module({ imports: [ConfigModule], @@ -12,7 +12,7 @@ import { PrismaWriteService } from "@/modules/prisma/prisma-write.service"; const service = new PrismaReadService(); service.setOptions({ readUrl: config.get("db.readUrl", { infer: true }), - maxReadConnections: parseInt(config.get("db.workerReadPoolMax", { infer: true }), 10), + maxReadConnections: parseInt(config.get("db.workerReadPoolMax", { infer: true })), e2e: config.get("e2e", { infer: true }) ?? false, type: "worker", }); @@ -26,7 +26,7 @@ import { PrismaWriteService } from "@/modules/prisma/prisma-write.service"; const service = new PrismaWriteService(); service.setOptions({ writeUrl: config.get("db.writeUrl", { infer: true }), - maxWriteConnections: parseInt(config.get("db.workerWritePoolMax", { infer: true }), 10), + maxWriteConnections: parseInt(config.get("db.workerWritePoolMax", { infer: true })), e2e: config.get("e2e", { infer: true }) ?? false, type: "worker", }); diff --git a/apps/api/v2/src/modules/prisma/prisma-write.service.ts b/apps/api/v2/src/modules/prisma/prisma-write.service.ts index c847b2d438..cb60985f1e 100644 --- a/apps/api/v2/src/modules/prisma/prisma-write.service.ts +++ b/apps/api/v2/src/modules/prisma/prisma-write.service.ts @@ -1,16 +1,16 @@ -import { PrismaClient } from "@calcom/prisma/client"; -import { Injectable, Logger, OnModuleDestroy, OnModuleInit } from "@nestjs/common"; +import { OnModuleDestroy, OnModuleInit, Injectable, Logger } from "@nestjs/common"; import { ConfigService } from "@nestjs/config"; import { PrismaPg } from "@prisma/adapter-pg"; import { Pool } from "pg"; +import { PrismaClient } from "@calcom/prisma/client"; + const DB_MAX_POOL_CONNECTION = 5; export interface PrismaServiceOptions { writeUrl?: string; maxWriteConnections?: number; e2e?: boolean; - usePool?: boolean; type: "main" | "worker"; } @@ -19,54 +19,41 @@ export class PrismaWriteService implements OnModuleInit, OnModuleDestroy { private logger = new Logger("PrismaWriteService"); public prisma!: PrismaClient; private pool!: Pool; + private options!: PrismaServiceOptions; - constructor(configService?: ConfigService) { + constructor(private configService?: ConfigService) { if (configService) { const writeUrl = configService.get("db.writeUrl", { infer: true }); const poolMax = parseInt( - String(configService.get("db.writePoolMax", { infer: true }) ?? DB_MAX_POOL_CONNECTION), - 10 + configService.get("db.writePoolMax", { infer: true }) ?? DB_MAX_POOL_CONNECTION ); const e2e = configService.get("e2e", { infer: true }) ?? false; - const usePool = configService.get("db.usePool", { infer: true }) ?? true; this.setOptions({ writeUrl, maxWriteConnections: poolMax, e2e, - usePool, type: "main", }); } } - setOptions(options: PrismaServiceOptions): void { + setOptions(options: PrismaServiceOptions) { + this.options = options; + const dbUrl = options.writeUrl; const isE2E = options.e2e ?? false; - const usePool = options.usePool ?? true; + this.pool = new Pool({ + connectionString: dbUrl, + max: isE2E ? 1 : options.maxWriteConnections ?? DB_MAX_POOL_CONNECTION, + idleTimeoutMillis: 300000, + }); - if (usePool) { - let maxWriteConnections = options.maxWriteConnections ?? DB_MAX_POOL_CONNECTION; - if (isE2E) { - maxWriteConnections = 1; - } - - this.pool = new Pool({ - connectionString: dbUrl, - max: maxWriteConnections, - idleTimeoutMillis: 300000, - }); - - const adapter = new PrismaPg(this.pool); - this.prisma = new PrismaClient({ adapter }); - } else { - this.prisma = new PrismaClient({ - datasourceUrl: dbUrl, - }); - } + const adapter = new PrismaPg(this.pool); + this.prisma = new PrismaClient({ adapter }); } - async onModuleInit(): Promise { + async onModuleInit() { if (!this.prisma) return; try { @@ -77,7 +64,7 @@ export class PrismaWriteService implements OnModuleInit, OnModuleDestroy { } } - async onModuleDestroy(): Promise { + async onModuleDestroy() { try { if (this.prisma) await this.prisma.$disconnect(); if (this.pool) await this.pool.end(); diff --git a/apps/api/v2/src/modules/prisma/prisma.module.ts b/apps/api/v2/src/modules/prisma/prisma.module.ts index 4bb8ae53b3..3c5d0d7565 100644 --- a/apps/api/v2/src/modules/prisma/prisma.module.ts +++ b/apps/api/v2/src/modules/prisma/prisma.module.ts @@ -1,7 +1,7 @@ -import { Module } from "@nestjs/common"; -import { ConfigModule, ConfigService } from "@nestjs/config"; import { PrismaReadService } from "@/modules/prisma/prisma-read.service"; import { PrismaWriteService } from "@/modules/prisma/prisma-write.service"; +import { Module } from "@nestjs/common"; +import { ConfigModule, ConfigService } from "@nestjs/config"; @Module({ imports: [ConfigModule], @@ -12,7 +12,7 @@ import { PrismaWriteService } from "@/modules/prisma/prisma-write.service"; const service = new PrismaReadService(); service.setOptions({ readUrl: config.get("db.readUrl", { infer: true }), - maxReadConnections: parseInt(config.get("db.readPoolMax", { infer: true }), 10), + maxReadConnections: parseInt(config.get("db.readPoolMax", { infer: true })), e2e: config.get("e2e", { infer: true }) ?? false, type: "main", }); @@ -26,7 +26,7 @@ import { PrismaWriteService } from "@/modules/prisma/prisma-write.service"; const service = new PrismaWriteService(); service.setOptions({ writeUrl: config.get("db.writeUrl", { infer: true }), - maxWriteConnections: parseInt(config.get("db.writePoolMax", { infer: true }), 10), + maxWriteConnections: parseInt(config.get("db.writePoolMax", { infer: true })), e2e: config.get("e2e", { infer: true }) ?? false, type: "main", }); diff --git a/apps/api/v2/src/swagger/generate-swagger-script.ts b/apps/api/v2/src/swagger/generate-swagger-script.ts index 96ef4a7b5b..14b9b6fa47 100644 --- a/apps/api/v2/src/swagger/generate-swagger-script.ts +++ b/apps/api/v2/src/swagger/generate-swagger-script.ts @@ -1,4 +1,5 @@ import "dotenv/config"; +import process from "node:process"; import { bootstrap } from "../bootstrap"; import { createNestApp } from "../main"; diff --git a/biome.json b/biome.json index fe8b052096..96312d5b9c 100644 --- a/biome.json +++ b/biome.json @@ -78,6 +78,16 @@ "linter": { "enabled": false }, "formatter": { "enabled": false } }, + { + "includes": ["apps/api/v2/**/*.ts", "apps/api/v2/**/*.controller.ts"], + "linter": { + "rules": { + "style": { + "useImportType": "off" + } + } + } + }, { "includes": ["**/*.tsx"], "javascript": { @@ -148,20 +158,6 @@ } } }, - { - "includes": ["apps/api/v2/**/*.ts", "apps/api/v2/**/*.controller.ts"], - "linter": { - "rules": { - "style": { - "useImportType": "off", - "noProcessEnv": "off" - }, - "correctness": { - "noProcessGlobal": "off" - } - } - } - }, { "includes": ["**/*.test.ts", "**/*.test.tsx", "**/*.e2e-spec.ts"], "linter": {