mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-28 12:04:41 +01:00
fix(db): honor the prepared-statement opt-in for ORM queries (#17673)
Drizzle calls Postgres.js unsafe queries, which disable preparation unless per-query options enable it. The existing client-level opt-in therefore does not prepare ORM queries. Honor explicit true across root and child clients. Preserve defaults, per-query options, lazy execution, and driver error handling. Document the pooler capability requirement. Test with 92 selected database and connection checks, workspace typechecks, server and database builds, and a read-only hosted ORM protocol probe. Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
1 parent
a8e63f0e2a
commit
1a3f604097
6 files changed
+259
-15
No files matched your search
@@ -56,12 +56,19 @@ For production, use a hosted provider like [Supabase](https://supabase.com/).
|
||||
|
||||
Use the **direct connection** (port 5432) for migrations and the **pooled connection** (port 6543) for the application.
|
||||
|
||||
If using connection pooling (transaction mode), disable prepared statements via the environment — no source edits needed:
|
||||
If your transaction-mode pooler does not support protocol-level named prepared statements, disable them via the environment:
|
||||
|
||||
```sh
|
||||
DATABASE_PREPARED_STATEMENTS=false
|
||||
```
|
||||
|
||||
For a direct connection or a pooler that supports named prepared statements,
|
||||
`DATABASE_PREPARED_STATEMENTS=true` also prepares parameterized ORM queries and
|
||||
queries inside transactions and reserved or dedicated connections. Check the
|
||||
provider's configuration before you enable it. Preparation caches statement
|
||||
metadata, not query results. Unset preserves the existing ORM behavior and the
|
||||
driver default for tagged SQL. Explicit per-query options still apply.
|
||||
|
||||
Related optional client tuning: `DATABASE_POOL_MAX`, `DATABASE_IDLE_TIMEOUT_SECONDS`, `DATABASE_CONNECT_TIMEOUT_SECONDS`, `DATABASE_MAX_LIFETIME_SECONDS`, `DATABASE_APPLICATION_NAME`. Driver defaults apply when unset, except that idle pooled connections close after 60 seconds (`DATABASE_IDLE_TIMEOUT_SECONDS=0` keeps them open) and the pool reports `application_name=paperclip`. See [Connection pool settings](#connection-pool-settings).
|
||||
|
||||
## Connection Pool Settings
|
||||
@@ -75,7 +82,7 @@ The server opens one postgres.js pool for its own queries (and a second one when
|
||||
| `DATABASE_CONNECT_TIMEOUT_SECONDS` | `30` (driver) | Give up on a connection attempt after this long. |
|
||||
| `DATABASE_MAX_LIFETIME_SECONDS` | 30–60 min, randomized (driver) | Recycle a pooled connection once it is this old. |
|
||||
| `DATABASE_APPLICATION_NAME` | `paperclip` | Value of `application_name` in `pg_stat_activity`, so you can find Paperclip's backends: `SELECT * FROM pg_stat_activity WHERE application_name = 'paperclip';` |
|
||||
| `DATABASE_PREPARED_STATEMENTS` | `true` (driver) | Set `false` behind a transaction-mode pooler (see above). |
|
||||
| `DATABASE_PREPARED_STATEMENTS` | Unset | `true` opts parameterized ORM queries into preparation. `false` disables preparation. Use `false` when the pooler does not support named statements. Unset preserves existing behavior. |
|
||||
|
||||
The server ends its pools during shutdown (SIGINT/SIGTERM) and when startup fails after the pool was opened, so a restarting server does not leave idle backends behind. Size `max_connections` on the PostgreSQL side for at least `DATABASE_POOL_MAX` per server process plus your other clients. Each server process also opens up to 2 connections (`application_name=paperclip-controller-lease`) for agent-run lease renewals, so they never queue behind slow application queries; count those too.
|
||||
|
||||
|
||||
Reference in new issue
Block a user