|
8 | 8 | type PrismaTransactionOptions, |
9 | 9 | } from "@trigger.dev/database"; |
10 | 10 | import { PrismaPg } from "@prisma/adapter-pg"; |
| 11 | +import { createHash } from "node:crypto"; |
11 | 12 | import invariant from "tiny-invariant"; |
12 | 13 | import { z } from "zod"; |
13 | 14 | import { env } from "./env.server"; |
@@ -117,12 +118,20 @@ function getClient() { |
117 | 118 |
|
118 | 119 | console.log(`🔌 setting up prisma client to ${redactUrlSecrets(databaseUrl)}`); |
119 | 120 |
|
120 | | - const adapter = new PrismaPg({ |
121 | | - connectionString: databaseUrl.href, |
122 | | - max: env.DATABASE_CONNECTION_LIMIT, |
123 | | - idleTimeoutMillis: env.DATABASE_CONNECTION_TIMEOUT * 1000, |
124 | | - connectionTimeoutMillis: env.DATABASE_CONNECTION_TIMEOUT * 1000, |
125 | | - }); |
| 121 | + const adapter = new PrismaPg( |
| 122 | + { |
| 123 | + connectionString: databaseUrl.href, |
| 124 | + max: env.DATABASE_CONNECTION_LIMIT, |
| 125 | + idleTimeoutMillis: env.DATABASE_CONNECTION_TIMEOUT * 1000, |
| 126 | + connectionTimeoutMillis: env.DATABASE_CONNECTION_TIMEOUT * 1000, |
| 127 | + }, |
| 128 | + { |
| 129 | + // Generate deterministic prepared statement names from query SQL so PostgreSQL |
| 130 | + // can reuse cached query plans. Without this, every query uses an anonymous |
| 131 | + // prepared statement that PG must parse and plan from scratch each time. |
| 132 | + statementNameGenerator: (query) => `p_${createHash("sha256").update(query.sql).digest("hex").slice(0, 16)}`, |
| 133 | + } |
| 134 | + ); |
126 | 135 |
|
127 | 136 | const client = new PrismaClient({ |
128 | 137 | adapter, |
@@ -240,12 +249,17 @@ function getReplicaClient() { |
240 | 249 |
|
241 | 250 | console.log(`🔌 setting up read replica connection to ${redactUrlSecrets(replicaUrl)}`); |
242 | 251 |
|
243 | | - const adapter = new PrismaPg({ |
244 | | - connectionString: replicaUrl.href, |
245 | | - max: env.DATABASE_CONNECTION_LIMIT, |
246 | | - idleTimeoutMillis: env.DATABASE_CONNECTION_TIMEOUT * 1000, |
247 | | - connectionTimeoutMillis: env.DATABASE_CONNECTION_TIMEOUT * 1000, |
248 | | - }); |
| 252 | + const adapter = new PrismaPg( |
| 253 | + { |
| 254 | + connectionString: replicaUrl.href, |
| 255 | + max: env.DATABASE_CONNECTION_LIMIT, |
| 256 | + idleTimeoutMillis: env.DATABASE_CONNECTION_TIMEOUT * 1000, |
| 257 | + connectionTimeoutMillis: env.DATABASE_CONNECTION_TIMEOUT * 1000, |
| 258 | + }, |
| 259 | + { |
| 260 | + statementNameGenerator: (query) => `p_${createHash("sha256").update(query.sql).digest("hex").slice(0, 16)}`, |
| 261 | + } |
| 262 | + ); |
249 | 263 |
|
250 | 264 | const replicaClient = new PrismaClient({ |
251 | 265 | adapter, |
|
0 commit comments