Skip to content
Merged
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
7 changes: 7 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
DATABASE_URL=postgres://postgres:postgres@127.0.0.1:5432/postgres

# Cloud SQL Auth Proxy (Unix socket) — set these instead of DATABASE_URL on Cloud Run.
# INSTANCE_UNIX_SOCKET=/cloudsql/PROJECT:REGION:INSTANCE
# DB_USER=your_db_user
# DB_PASSWORD=****
# DB_NAME=your_db_name
# DB_USE_UNIX_SOCKET=true # set to "false" to force DATABASE_URL even when INSTANCE_UNIX_SOCKET is set

# `openssl rand -hex 32`
NEXTAUTH_SECRET=****

Expand Down
19 changes: 19 additions & 0 deletions apphosting.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,22 @@ env:
availability:
- BUILD
- RUNTIME

# Cloud SQL Auth Proxy (Unix socket) connection.
# Set INSTANCE_UNIX_SOCKET to enable; set DB_USE_UNIX_SOCKET=false to force DATABASE_URL fallback.
- variable: INSTANCE_UNIX_SOCKET
value: /cloudsql/f3data:us-central1:f3data
availability:
- RUNTIME
- variable: DB_USER
value: app_codex
availability:
- RUNTIME
- variable: DB_PASSWORD
secret: client-database-password
availability:
- RUNTIME
- variable: DB_NAME
value: f3_prod
availability:
- RUNTIME
36 changes: 35 additions & 1 deletion src/lib/db.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,44 @@ import { Pool, type PoolClient } from "pg";
let pool: Pool | null = null;

function initializePool(): Pool {
const instanceUnixSocket = process.env.INSTANCE_UNIX_SOCKET; // e.g. /cloudsql/PROJECT:REGION:INSTANCE
const useUnixSocket =
instanceUnixSocket && process.env.DB_USE_UNIX_SOCKET !== "false";

if (useUnixSocket) {
const dbUser = process.env.DB_USER;
const dbPassword = process.env.DB_PASSWORD;
const dbName = process.env.DB_NAME;

if (!dbUser || !dbName) {
throw new Error(
"INSTANCE_UNIX_SOCKET is set but DB_USER and/or DB_NAME are missing.",
);
}

const newPool = new Pool({
user: dbUser,
password: dbPassword,
database: dbName,
host: instanceUnixSocket,
});

newPool.on("error", (err) => {
console.error("Unexpected error on idle PostgreSQL client:", err);
});

console.log("✅ PostgreSQL pool initialized via Cloud SQL Unix socket.");
return newPool;
}

// Fallback: direct TCP connection via DATABASE_URL
const connectionString = process.env.DATABASE_URL;

if (!connectionString) {
console.error("❌ CRITICAL: DATABASE_URL is not set in the environment.");
throw new Error("DATABASE_URL is missing. Cannot connect to the database.");
throw new Error(
"Neither INSTANCE_UNIX_SOCKET nor DATABASE_URL is configured. Cannot connect to the database.",
);
}

const isProduction = process.env.NODE_ENV === "production";
Expand All @@ -23,6 +56,7 @@ function initializePool(): Pool {
console.error("Unexpected error on idle PostgreSQL client:", err);
});

console.log("✅ PostgreSQL pool initialized via DATABASE_URL (TCP).");
return newPool;
}

Expand Down
Loading