perf: batch gateway submits and isolate callbacks

This commit is contained in:
hectorzhao
2026-08-25 11:39:59 +08:00
parent c6f11014d6
commit 761c123b65
29 changed files with 1912 additions and 193 deletions
+41 -16
View File
@@ -1,30 +1,46 @@
import { Injectable, OnModuleDestroy } from '@nestjs/common';
import { PrismaPg } from '@prisma/adapter-pg';
import { PrismaClient } from '@prisma/client';
import { Pool } from 'pg';
import { requestContext } from '../common/request-context';
@Injectable()
export class PrismaService extends PrismaClient implements OnModuleDestroy {
private readonly databasePool: Pool;
private readonly databasePoolMax: number;
constructor() {
const workerRole = process.env.CMPP_PROCESS_ROLE === 'worker';
const databaseUrl = workerRole
? process.env.API_WORKER_DATABASE_URL || process.env.DATABASE_URL
: process.env.DATABASE_URL;
const configuredPoolMax = Number(workerRole
? process.env.API_WORKER_DB_POOL_MAX ?? 8
: process.env.API_DB_POOL_MAX ?? 32);
const processRole = process.env.CMPP_PROCESS_ROLE?.trim() || 'api';
const workerRole = processRole === 'worker';
const outboxRole = processRole === 'outbox';
const callbackRole = processRole === 'callback';
const databaseUrl = outboxRole
? process.env.API_OUTBOX_DATABASE_URL || process.env.DATABASE_URL
: callbackRole
? process.env.API_CALLBACK_DATABASE_URL || process.env.DATABASE_URL
: workerRole
? process.env.API_WORKER_DATABASE_URL || process.env.DATABASE_URL
: process.env.DATABASE_URL;
const configuredPoolMax = Number(outboxRole
? process.env.API_OUTBOX_DB_POOL_MAX ?? 6
: callbackRole
? process.env.API_CALLBACK_DB_POOL_MAX ?? 16
: workerRole
? process.env.API_WORKER_DB_POOL_MAX ?? 8
: process.env.API_DB_POOL_MAX ?? 32);
const poolMax = Number.isInteger(configuredPoolMax) && configuredPoolMax > 0
? configuredPoolMax
: workerRole ? 8 : 32;
super({
adapter: new PrismaPg({
connectionString: databaseUrl
?? 'postgresql://cmpp:cmpp_password@localhost:5432/cmpp_platform?schema=public',
// API capacity must be reserved independently from the heavier Worker
// transactions; explicit bounds also protect PostgreSQL max_connections.
max: poolMax,
}),
: outboxRole ? 6 : callbackRole ? 16 : workerRole ? 8 : 32;
const databasePool = new Pool({
connectionString: databaseUrl
?? 'postgresql://cmpp:cmpp_password@localhost:5432/cmpp_platform?schema=public',
// API capacity must be reserved independently from the heavier Worker
// transactions; explicit bounds also protect PostgreSQL max_connections.
max: poolMax,
});
super({ adapter: new PrismaPg(databasePool, { disposeExternalPool: true }) });
this.databasePool = databasePool;
this.databasePoolMax = poolMax;
const operationLog = this.operationLog;
Object.defineProperty(this, 'operationLog', {
value: new Proxy(operationLog, {
@@ -46,6 +62,15 @@ export class PrismaService extends PrismaClient implements OnModuleDestroy {
});
}
getPoolState() {
return {
max: this.databasePoolMax,
total: this.databasePool.totalCount,
idle: this.databasePool.idleCount,
waiting: this.databasePool.waitingCount,
};
}
async onModuleDestroy() {
await this.$disconnect();
}