fix: block until provisioned database accepts connections - #84
fix: block until provisioned database accepts connections#84AmanVarshney01 wants to merge 1 commit into
Conversation
Deploying with
|
| Status | Name | Latest Commit | Updated (UTC) |
|---|---|---|---|
| ❌ Deployment failed View logs |
create-db-worker | 9ef091d | Jul 19 2026, 10:23 PM |
Deploying with
|
| Status | Name | Latest Commit | Updated (UTC) |
|---|---|---|---|
| ❌ Deployment failed View logs |
claim-db-worker | 9ef091d | Jul 19 2026, 10:23 PM |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (3)
🚧 Files skipped from review as they are similar to previous changes (3)
Walkthrough
ChangesDatabase readiness reporting
Estimated code review effort: 3 (Moderate) | ~20 minutes 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
Comment |
|
✅ Preview CLIs & Workers are live! Test the CLIs locally under tag npx create-db@pr84
npx create-pg@pr84
npx create-postgres@pr84Worker URLs
|
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@packages/create-db/src/core/database.ts`:
- Around line 20-23: Update waitForDatabaseReady so skipped probes return
undefined rather than true for unsupported or pooled URLs, and when
connectionString is missing, distinguishing “not probed” from a failed readiness
check. Preserve true/false results for URLs that are actually probed, and update
callers to handle the undefined result without treating it as ready or timed
out.
- Around line 25-34: Update the readiness retry loop around the ppg.sql probe
and collect call to cap the retry delay at the remaining deadline, avoiding a
fixed 500ms sleep after the budget is nearly exhausted. Preserve successful
probes, and ensure the function returns false once the deadline is reached; if a
hard cutoff is needed, add an outer timeout around the stalled collect
operation.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 28fb0893-5b72-4825-8b2b-f4d74ca3613f
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (3)
packages/create-db/package.jsonpackages/create-db/src/core/database.tspackages/create-db/src/types.ts
| // Only direct TCP URLs can be probed with @prisma/ppg. | ||
| if (!/^postgres(ql)?:\/\//.test(connectionString)) { | ||
| return true; | ||
| } |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
git ls-files 'packages/create-db/src/core/database.ts' 'packages/create-db/src/core/*' 'packages/create-db/src/**' | sed -n '1,120p'
echo '--- outline ---'
ast-grep outline packages/create-db/src/core/database.ts --view expanded || true
echo '--- lines 1-260 ---'
sed -n '1,260p' packages/create-db/src/core/database.ts
echo '--- search ready/usages ---'
rg -n "\bready\b|createDatabaseCore|probe" packages/create-db/src -SRepository: prisma/create-db
Length of output: 7139
Don't encode skipped probes as ready: true.
waitForDatabaseReady() returns true for any non-postgres:// URL, so a pooled prisma+postgres:// connection is marked ready even though no probe ran. It also returns false when connectionString is missing, which conflates “not probed” with “timed out”. Return undefined for skipped probes, or split the result into “probed” and “ready”.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/create-db/src/core/database.ts` around lines 20 - 23, Update
waitForDatabaseReady so skipped probes return undefined rather than true for
unsupported or pooled URLs, and when connectionString is missing, distinguishing
“not probed” from a failed readiness check. Preserve true/false results for URLs
that are actually probed, and update callers to handle the undefined result
without treating it as ready or timed out.
Source: MCP tools
| const deadline = Date.now() + timeoutMs; | ||
| while (Date.now() < deadline) { | ||
| try { | ||
| const ppg = prismaPostgres(defaultClientConfig(connectionString)); | ||
| await ppg.sql`SELECT 1`.collect(); | ||
| return true; | ||
| } catch { | ||
| await new Promise((resolve) => | ||
| setTimeout(resolve, READINESS_RETRY_DELAY_MS) | ||
| ); |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Map relevant files
git ls-files 'packages/create-db/**' | sed -n '1,200p'
printf '\n--- database.ts ---\n'
wc -l packages/create-db/src/core/database.ts
cat -n packages/create-db/src/core/database.ts
printf '\n--- search for timeout/abort helpers ---\n'
rg -n "AbortController|abort|timeout|READINESS_RETRY_DELAY_MS|collect\\(\\)|prismaPostgres|SELECT 1" packages/create-db -SRepository: prisma/create-db
Length of output: 9717
🌐 Web query:
@prisma/ppg AbortController timeout collect prismaPostgres sql timeout abort signal
💡 Result:
As of July 2026, the @prisma/ppg (Prisma Postgres serverless driver) library does not natively support AbortController or AbortSignal for canceling database queries [1][2][3]. While AbortController is a widely adopted standard in Node.js and web environments for cancelling asynchronous operations, it is not currently integrated into the @prisma/ppg query execution flow [4][5][6]. Consequently, there is no mechanism to pass an AbortSignal to the client's sql, query, or exec methods to terminate a long-running database request before it finishes [2][3]. Regarding timeouts and query management: - Query Timeouts: Prisma Postgres enforces internal timeouts depending on the connection type [7][8]. For pooled connections (common for application traffic), there is a 10-minute query timeout [8]. When using direct connections, specific, shorter timeouts apply (e.g., up to 10 seconds for standard queries, 15 seconds for interactive transactions) [7]. - Client Limitations: The @prisma/ppg client is designed for HTTP and WebSocket-based communication [1][8]. Because it manages its own transport layer, users cannot manually implement AbortController at the driver level to "force" the cancellation of a network request sent through this client [2][3]. If your use case requires preventing long-running operations from consuming resources, you must rely on server-side configuration and the inherent timeout limits enforced by the Prisma Postgres infrastructure rather than client-side signals [7][8]. [1][4][2][3][7][8]
Citations:
- 1: https://www.prisma.io/docs/postgres/database/serverless-driver
- 2: https://registry.npmjs.org/%40prisma%2Fppg
- 3: https://github.com/prisma/ppg-client/
- 4: Support query cancellation with
AbortController/AbortSignalprisma#15594 - 5: https://www.answeroverflow.com/m/1392365414272733254
- 6: Canceling queries (AbortController / AbortSignal) prisma#12720
- 7: https://github.com/prisma/docs/blob/7f69693b/content/250-postgres/300-database/650-direct-connections.mdx
- 8: https://www.prisma.io/docs/postgres/database/connecting-to-your-database
🌐 Web query:
@prisma/ppg defaultClientConfig timeout query cancellation direct connection options
💡 Result:
The @prisma/ppg library (also known as the Prisma Postgres serverless driver) is designed for serverless and edge environments, communicating via HTTP and WebSockets rather than the standard PostgreSQL TCP wire protocol [1][2][3]. Regarding your specific configuration and features: 1. defaultClientConfig: This function is used to initialize the client configuration, typically with the Prisma Postgres Direct TCP URL [1][4][5]. It automatically includes essential type parsers and serializers (for types like Date, JSON, and BigInt) [4][5]. Usage typically looks like this: const ppg = prismaPostgres(defaultClientConfig(process.env.PRISMA_DIRECT_TCP_URL!)); 2. Timeout and Query Cancellation: The @prisma/ppg driver itself does not expose explicit configuration options for query-level timeouts or cancellation via a standard API (such as an AbortController signal) in the same manner as some other fetch-based libraries [1][4][5]. Prisma ORM generally manages its own timeouts separate from database drivers [6][7]. For long-running queries in Prisma Postgres environments, be aware that pooled connections enforce a 10-minute timeout [2][8]. If your workload requires longer execution times or complex session states, you must use a direct connection, which bypasses the pooler [2][8]. 3. Direct Connection Options: While @prisma/ppg requires a "Direct TCP Connection" URL, it is important to clarify that this is used for routing and identification [1][2]. The transport remains HTTP/WebSocket [2]. If you are performing operations that require a true TCP-based direct connection—such as migrations, introspection, or specific session-level commands like LISTEN/NOTIFY—you should use the standard Prisma Client with the appropriate driver adapter (e.g., @prisma/adapter-pg) rather than the @prisma/ppg serverless driver [2][3][8]. In summary, @prisma/ppg is optimized for serverless performance and automatic connection pooling; if you find yourself needing low-level manual timeout controls or native TCP features, you are likely looking for the standard Prisma driver adapter approach instead [2][6][3].
Citations:
- 1: https://www.prisma.io/docs/postgres/database/serverless-driver
- 2: https://www.prisma.io/docs/postgres/database/connecting-to-your-database
- 3: https://github.com/prisma/prisma/blob/7.8.0-dev.3/packages/adapter-ppg/README.md
- 4: https://github.com/prisma/ppg-client
- 5: https://registry.npmjs.org/%40prisma%2Fppg
- 6: https://www.prisma.io/docs/v6/orm/prisma-client/setup-and-configuration/databases-connections
- 7: https://www.prisma.io/docs/orm/prisma-client/setup-and-configuration/databases-connections/connection-pool
- 8: https://www.prisma.io/docs/postgres/database/connection-pooling
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Look for tests or call sites that rely on the readiness timeout behavior.
rg -n "waitForDatabaseReady|ready:\s*|READINESS_TIMEOUT_MS|createDatabaseCore\(" packages/create-db -SRepository: prisma/create-db
Length of output: 643
Treat this as a soft deadline. @prisma/ppg doesn’t expose query cancellation, so a stalled collect() can run past 30s and the fixed 500ms backoff can add extra delay. Cap the sleep to the remaining budget, and if a hard cutoff is required, wrap the probe in an outer timeout and return false when it expires.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/create-db/src/core/database.ts` around lines 25 - 34, Update the
readiness retry loop around the ppg.sql probe and collect call to cap the retry
delay at the remaining deadline, avoiding a fixed 500ms sleep after the budget
is nearly exhausted. Preserve successful probes, and ensure the function returns
false once the deadline is reached; if a hard cutoff is needed, add an outer
timeout around the stalled collect operation.
A freshly created database could be returned to callers before it accepted connections, so consumers that connect immediately (e.g. create-prisma running the first migration) raced provisioning and sometimes failed. create-prisma currently works around this with a blind 2s sleep. Probe the direct TCP connection string with SELECT 1 (via @prisma/ppg, 500ms backoff, 30s cap) inside createDatabaseCore before returning, so every consumer path (CLI flags and programmatic create()) gets a connection string that is known to work. The probe is non-fatal on timeout and surfaces an additive `ready` field on the result. Measured cost when the database is already reachable: one query round trip (~0.5-1s to ap-southeast-1).
cf01e11 to
9ef091d
Compare
|
✅ Preview CLIs & Workers are live! Test the CLIs locally under tag npx create-db@pr84
npx create-pg@pr84
npx create-postgres@pr84Worker URLs
|
Problem
createDatabaseCorereturns the connection string the momentapi.prisma.io/v1/projectsresponds (the create-db worker is a verbatim pass-through), with no readiness gate anywhere in the stack. A freshly provisioned database can briefly reject connections, so consumers that connect immediately race provisioning —create-prismacurrently works around this with a blind 2s sleep before running the firstprisma migrate dev.Fix
Probe the direct TCP connection string with
SELECT 1(via@prisma/ppg, 500ms backoff, 30s cap) insidecreateDatabaseCorebefore returning. This is the single choke point, so every consumer path benefits:--json,--quiet,--env, interactive, and the programmaticcreate()export.ready?: booleanon the result.prisma+postgres://) URLs are skipped rather than probed.@prisma/ppgleaves no open handles: process exits cleanly after the probe under both Node 24 and Bun 1.3.Cost
When the database is already reachable the probe is one query round trip — measured ~0.5–1s (to
ap-southeast-1). It only waits when the database genuinely isn't accepting connections yet, i.e. exactly when returning early would hand out a broken URL. If the added latency is a concern for barenpx create-dbusage, a--no-waitflag would be an easy follow-up — happy to add it.Honesty note on reproduction
In 5 fresh provisions today the database answered on the first attempt (
ready: true, no retries), so the race is rare/intermittent — this gate is cheap insurance that also lets create-prisma delete its unconditional 2s sleep (net faster for that flow).Testing
pnpm typecheck,pnpm buildcleannode dist/cli.mjs --json→"ready": truewith normal wall-clock timeSummary by CodeRabbit
readyflag indicating whether the readiness check succeeded.