Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/create-db/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
"dependencies": {
"@clack/prompts": "^0.11.0",
"@orpc/server": "^1.12.2",
"@prisma/ppg": "^1.0.1",
"dotenv": "^17.2.3",
"execa": "^9.6.1",
"picocolors": "^1.1.1",
Expand Down
33 changes: 33 additions & 0 deletions packages/create-db/src/core/database.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,35 @@
import { randomUUID } from "crypto";
import { defaultClientConfig, prismaPostgres } from "@prisma/ppg";
import type { ApiResponse, CreateDatabaseResult } from "../types.js";
import { sendAnalytics } from "../utils/analytics.js";

const READINESS_TIMEOUT_MS = 30_000;
const READINESS_RETRY_DELAY_MS = 500;

async function waitForDatabaseReady(
connectionString: string,
timeoutMs = READINESS_TIMEOUT_MS
): Promise<boolean> {
if (!/^postgres(ql)?:\/\//.test(connectionString)) {
return true;
}

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)
);
Comment on lines +17 to +26

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 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 -S

Repository: 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:


🌐 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:


🏁 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 -S

Repository: 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.

}
}

return false;
}

export function getCommandName(): string {
const executable = process.argv[1] || "create-db";
if (executable.includes("create-pg")) return "create-pg";
Expand Down Expand Up @@ -141,6 +169,10 @@ export async function createDatabaseCore(
createDbWorkerUrl
);

const ready = connectionString
? await waitForDatabaseReady(connectionString)
: false;

return {
success: true,
connectionString,
Expand All @@ -150,5 +182,6 @@ export async function createDatabaseCore(
name: database?.name ?? name,
projectId,
userAgent,
ready,
};
}
1 change: 1 addition & 0 deletions packages/create-db/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ export interface DatabaseResult {
name: string;
projectId: string;
userAgent?: string;
ready?: boolean;
}

export interface DatabaseError {
Expand Down
Loading
Loading