Skip to content

Commit 1c72e57

Browse files
ericallamclaude
andcommitted
fix(webapp,database): address Devin review on the driver-adapter path
- Pass the datasource schema (?schema=) to PrismaPg as its {schema} option so custom-schema installs keep talking to the right schema on the adapter (the adapter does not honor ?schema= in the connection string). - Set disposeExternalPool: true so $disconnect() closes the pg pool instead of leaking sockets, matching the engine-driver path. - Guard the two $metrics consumers (the /metrics route and the OTel batch observable callback) so a client on a driver adapter degrades to empty metrics instead of failing the scrape / rejecting the callback. - isPrismaRetriableError checks the adapter acquire-timeout message independently of the coded-error branch, so the pool-acquire retry still engages if the timeout arrives wrapped as a coded error. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent f07ac7c commit 1c72e57

4 files changed

Lines changed: 24 additions & 5 deletions

File tree

apps/webapp/app/db.server.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -456,7 +456,15 @@ function buildDriverAdapterPool(
456456
ignoreError: true,
457457
});
458458
});
459-
return new PrismaPg(pool);
459+
460+
let schema: string | undefined;
461+
try {
462+
schema = new URL(connectionString).searchParams.get("schema") ?? undefined;
463+
} catch {
464+
schema = undefined;
465+
}
466+
467+
return new PrismaPg(pool, { schema, disposeExternalPool: true });
460468
}
461469

462470
// Generalized writer builder shared by the control-plane client and the run-ops

apps/webapp/app/routes/metrics.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,12 @@ export async function loader({ request }: LoaderFunctionArgs) {
1414
}
1515

1616
// We need to remove empty lines from the prisma metrics, grafana doesn't like them
17-
const prismaMetrics = (await prisma.$metrics.prometheus()).replace(/^\s*[\r\n]/gm, "");
17+
let prismaMetrics = "";
18+
try {
19+
prismaMetrics = (await prisma.$metrics.prometheus()).replace(/^\s*[\r\n]/gm, "");
20+
} catch {
21+
prismaMetrics = "";
22+
}
1823
const coreMetrics = await metricsRegister.metrics();
1924

2025
// Order matters, core metrics end with `# EOF`, prisma metrics don't

apps/webapp/app/v3/tracer.server.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -551,7 +551,13 @@ function configurePrismaMetrics({ meter }: { meter: Meter }) {
551551

552552
meter.addBatchObservableCallback(
553553
async (res) => {
554-
const { counters, gauges, histograms } = await readPrismaMetrics();
554+
let prismaMetrics: Awaited<ReturnType<typeof readPrismaMetrics>>;
555+
try {
556+
prismaMetrics = await readPrismaMetrics();
557+
} catch {
558+
return;
559+
}
560+
const { counters, gauges, histograms } = prismaMetrics;
555561

556562
// Observe counters
557563
res.observe(queriesTotal, counters.queriesTotal);

internal-packages/database/src/transaction.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ const retryCodes = ["P2024", "P2028", "P2034"];
4040
const ADAPTER_ACQUIRE_TIMEOUT = /timeout exceeded when trying to connect/i;
4141

4242
export function isPrismaRetriableError(error: unknown): boolean {
43-
if (isPrismaKnownError(error)) {
44-
return retryCodes.includes(error.code);
43+
if (isPrismaKnownError(error) && retryCodes.includes(error.code)) {
44+
return true;
4545
}
4646

4747
const message = (error as { message?: unknown })?.message;

0 commit comments

Comments
 (0)