lilith-platform.live/codebase/@features/api/scripts/drop-test-db.ts

72 lines
2.3 KiB
TypeScript
Raw Normal View History

#!/usr/bin/env bun
/**
* Drop ONE throwaway test database by name.
*
* Two modes:
* bun scripts/drop-test-db.ts <name> drop now (with retries)
* bun scripts/drop-test-db.ts <name> --wait-for-pid N watcher mode: poll until
* pid N is gone, then drop
*
* Watcher mode is spawned detached by the test harness AT MODULE LOAD
* (src/__tests__/test-db.ts): a process-exit-hook spawn proved unreliable
* bun tears the process down before the child finishes exec'ing so instead
* a watcher outlives the test process by design and fires on its death,
* covering normal exit, crashes, and kills alike. A hard lifetime cap keeps
* a watcher from living forever if pid polling misbehaves.
*/
import postgres from 'postgres';
const name = process.argv[2];
if (!name || !/^quinn_test_[0-9a-z_]+$/.test(name)) {
process.stderr.write(`refusing to drop ${JSON.stringify(name)} — not a quinn_test_* name\n`);
process.exit(1);
}
const waitFlagIdx = process.argv.indexOf('--wait-for-pid');
const waitPid = waitFlagIdx !== -1 ? Number(process.argv[waitFlagIdx + 1]) : null;
if (waitFlagIdx !== -1 && (!Number.isInteger(waitPid) || waitPid! <= 0)) {
process.stderr.write(`--wait-for-pid needs a positive pid, got ${JSON.stringify(process.argv[waitFlagIdx + 1])}\n`);
process.exit(1);
}
const MAX_WATCH_MS = 3 * 3600_000;
function pidAlive(pid: number): boolean {
try {
process.kill(pid, 0);
return true;
} catch {
return false;
}
}
if (waitPid !== null) {
const startedAt = Date.now();
while (pidAlive(waitPid) && Date.now() - startedAt < MAX_WATCH_MS) {
await Bun.sleep(1000);
}
}
const adminUrl =
process.env['QUINN_TEST_ADMIN_DB_URL'] ?? 'postgresql://quinn:devpassword@black.lan:25435/postgres';
const admin = postgres(adminUrl, { max: 1, connect_timeout: 10, onnotice: () => { /* suppress */ } });
let lastErr: unknown;
for (let attempt = 0; attempt < 5; attempt += 1) {
await Bun.sleep(500 * (attempt + 1));
try {
await admin.unsafe(`DROP DATABASE IF EXISTS "${name}" WITH (FORCE)`);
lastErr = undefined;
break;
} catch (err) {
lastErr = err;
}
}
await admin.end();
if (lastErr !== undefined) {
process.stderr.write(`drop-test-db: ${name}: ${String(lastErr)}\n`);
process.exit(1);
}