| 87 | * Automatically retries once on transient connection errors. |
| 88 | */ |
| 89 | export async function query<T extends QueryResultRow = any>( |
| 90 | text: string, |
| 91 | params?: any[] |
| 92 | ): Promise<QueryResult<T>> { |
| 93 | const p = getPool(); |
| 94 | const start = process.hrtime.bigint(); |
| 95 | try { |
| 96 | return await p.query<T>(text, params); |
| 97 | } catch (err) { |
| 98 | if (isTransientConnectionError(err)) { |
| 99 | console.warn("Transient DB connection error, retrying query:", (err as Error).message); |
| 100 | return p.query<T>(text, params); |
| 101 | } |
| 102 | throw err; |
| 103 | } finally { |
| 104 | const durationMs = Number(process.hrtime.bigint() - start) / 1e6; |
| 105 | if (durationMs > SLOW_QUERY_THRESHOLD_MS) { |
| 106 | logger.warn({ duration_ms: Math.round(durationMs) }, "Slow database query"); |
| 107 | } |
| 108 | } |
| 109 | } |
| 110 | |
| 111 | /** |
| 112 | * Get a client from the pool for transactions. |