update
This commit is contained in:
+58
-24
@@ -1,36 +1,68 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* Wait until docker-compose Postgres is accepting connections.
|
||||
* Wait until DATABASE_URL Postgres accepts TCP connections.
|
||||
* Works with native Postgres or Docker-mapped ports (no docker CLI required).
|
||||
*
|
||||
* Usage: node scripts/wait-postgres.mjs
|
||||
*/
|
||||
import { spawnSync } from "node:child_process";
|
||||
import net from "node:net";
|
||||
import { setTimeout as delay } from "node:timers/promises";
|
||||
import { repoRoot } from "./root-env.mjs";
|
||||
import { loadRootEnv } from "./root-env.mjs";
|
||||
|
||||
const maxAttempts = Number(process.env.DESCRYBE_DB_WAIT_ATTEMPTS || 60);
|
||||
const sleepMs = Number(process.env.DESCRYBE_DB_WAIT_MS || 1000);
|
||||
|
||||
for (let i = 1; i <= maxAttempts; i++) {
|
||||
const r = spawnSync(
|
||||
"docker",
|
||||
[
|
||||
"compose",
|
||||
"exec",
|
||||
"-T",
|
||||
"postgres",
|
||||
"pg_isready",
|
||||
"-U",
|
||||
"descrybe",
|
||||
"-d",
|
||||
"descrybe",
|
||||
],
|
||||
{
|
||||
cwd: repoRoot,
|
||||
encoding: "utf8",
|
||||
shell: process.platform === "win32",
|
||||
},
|
||||
const env = loadRootEnv(process.env);
|
||||
const databaseUrl = env.DATABASE_URL;
|
||||
if (!databaseUrl || !String(databaseUrl).trim()) {
|
||||
console.error(
|
||||
"[db] DATABASE_URL is required (root .env or shell; see .env.example)",
|
||||
);
|
||||
if (r.status === 0) {
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
function parsePostgresTarget(urlStr) {
|
||||
let u;
|
||||
try {
|
||||
u = new URL(urlStr);
|
||||
} catch {
|
||||
console.error("[db] DATABASE_URL is not a valid URL");
|
||||
process.exit(1);
|
||||
}
|
||||
const protocol = (u.protocol || "").replace(/:$/, "");
|
||||
if (protocol !== "postgres" && protocol !== "postgresql") {
|
||||
console.error(`[db] DATABASE_URL must be postgres(ql)://… (got ${protocol})`);
|
||||
process.exit(1);
|
||||
}
|
||||
const host = u.hostname || "127.0.0.1";
|
||||
const port = Number(u.port || 5432);
|
||||
if (!Number.isFinite(port) || port <= 0) {
|
||||
console.error("[db] DATABASE_URL has an invalid port");
|
||||
process.exit(1);
|
||||
}
|
||||
return { host, port };
|
||||
}
|
||||
|
||||
function canConnect(host, port) {
|
||||
return new Promise((resolve) => {
|
||||
const socket = net.connect({ host, port });
|
||||
const done = (ok) => {
|
||||
socket.removeAllListeners();
|
||||
socket.destroy();
|
||||
resolve(ok);
|
||||
};
|
||||
socket.setTimeout(2000);
|
||||
socket.once("connect", () => done(true));
|
||||
socket.once("timeout", () => done(false));
|
||||
socket.once("error", () => done(false));
|
||||
});
|
||||
}
|
||||
|
||||
const { host, port } = parsePostgresTarget(databaseUrl);
|
||||
console.log(`[db] waiting for Postgres at ${host}:${port}`);
|
||||
|
||||
for (let i = 1; i <= maxAttempts; i++) {
|
||||
if (await canConnect(host, port)) {
|
||||
console.log(`[db] postgres ready (attempt ${i})`);
|
||||
process.exit(0);
|
||||
}
|
||||
@@ -39,5 +71,7 @@ for (let i = 1; i <= maxAttempts; i++) {
|
||||
}
|
||||
|
||||
console.error("\n[db] postgres did not become ready in time");
|
||||
console.error("Check: docker compose ps && docker compose logs postgres");
|
||||
console.error(`Check: DATABASE_URL host ${host}:${port} is up and listening`);
|
||||
console.error("Native: sudo systemctl status postgresql");
|
||||
console.error("Docker (optional local): docker compose ps && docker compose logs postgres");
|
||||
process.exit(1);
|
||||
|
||||
Reference in New Issue
Block a user