/ opencodehub / scripts / drill-postgres-reconnect.ts
Swadhin Biswas Feature/ai code reviewer (#79) · 8/16/2026
cfd400d
93 lines · 3.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
/**
 * PostgreSQL Reconnect Drill (weekly / manual)
 *
 * Verifies the database layer survives an outage + reconnect cycle:
 *   1. Confirm the DB is connected
 *   2. Close the pool (simulating an outage)
 *   3. Reconnect via getDatabase()
 *   4. Run a real query and confirm results
 *
 * Env:
 *   DATABASE_URL — the PostgreSQL connection string to exercise
 *
 * Exit code 0 on success, 1 on any drill failure.
 */
import { mkdirSync, writeFileSync } from "node:fs";
import { dirname, join } from "node:path";
import { fileURLToPath } from "node:url";

const __dirname = dirname(fileURLToPath(import.meta.url));
const rootDir = join(__dirname, "..");
const reportDir = join(rootDir, "test-results", "drills");
mkdirSync(reportDir, { recursive: true });

const started = Date.now();
const results: Record<string, string> = {};

function ok(name: string, detail = "") {
  results[name] = `PASS${detail ? `: ${detail}` : ""}`;
  console.log(`✅ ${name}${detail ? ` — ${detail}` : ""}`);
}
function fail(name: string, detail: string) {
  results[name] = `FAIL: ${detail}`;
  console.error(`❌ ${name} — ${detail}`);
}

async function main() {
  // ── Step 1: initial connection ────────────────────────────────────
  try {
    const { getDatabase, isDatabaseConnected } = await import("../src/db/index");
    const db = getDatabase();
    const connected = isDatabaseConnected();
    if (!connected) throw new Error("database reports disconnected at start");
    ok("initial-connection", "pool connected");
  } catch (e) {
    fail("initial-connection", e instanceof Error ? e.message : String(e));
  }

  // ── Step 2: simulate outage (close pool) ──────────────────────────
  try {
    const { closeDatabase } = await import("../src/db/index");
    await closeDatabase();
    ok("outage-simulation", "pool closed cleanly");
  } catch (e) {
    fail("outage-simulation", e instanceof Error ? e.message : String(e));
  }

  // ── Step 3: reconnect ─────────────────────────────────────────────
  try {
    const { getDatabase, isDatabaseConnected } = await import("../src/db/index");
    const db = getDatabase();
    if (!db) throw new Error("getDatabase() returned null after reconnect");
    ok("reconnect", "pool re-created");
  } catch (e) {
    fail("reconnect", e instanceof Error ? e.message : String(e));
  }

  // ── Step 4: real query round-trip ─────────────────────────────────
  try {
    const { getDatabase, schema } = await import("../src/db/index");
    const db = getDatabase();
    const row = await db.query.users.findFirst();
    // A successful query (row may be null on an empty DB) proves the
    // connection + schema registration both work post-reconnect.
    ok("query-roundtrip", row ? `users table readable` : "users table empty but queryable");
  } catch (e) {
    fail("query-roundtrip", e instanceof Error ? e.message : String(e));
  }

  const passed = Object.values(results).every((r) => r.startsWith("PASS"));
  writeFileSync(
    join(reportDir, "postgres-reconnect-report.json"),
    JSON.stringify({ drill: "postgres-reconnect", timestamp: new Date().toISOString(), durationMs: Date.now() - started, results, passed }, null, 2),
  );
  console.log("\n" + JSON.stringify(results, null, 2));
  console.log(passed ? "\n✅ PostgreSQL reconnect drill PASSED" : "\n❌ PostgreSQL reconnect drill FAILED");
  process.exit(passed ? 0 : 1);
}

main().catch((e) => {
  console.error("Drill crashed:", e);
  process.exit(1);
});