Production readiness hardening and ops tooling
This commit is contained in:
72
scripts/restore-drill-validate.mjs
Normal file
72
scripts/restore-drill-validate.mjs
Normal file
@ -0,0 +1,72 @@
|
||||
#!/usr/bin/env node
|
||||
import { spawnSync } from "node:child_process";
|
||||
import { Pool } from "pg";
|
||||
import "dotenv/config";
|
||||
|
||||
const baseUrl = process.env.BASE_URL || `http://127.0.0.1:${process.env.PORT || 3000}`;
|
||||
const adminToken = process.env.ADMIN_TOKEN || "admin-dev-token";
|
||||
const runMigrate = process.env.RESTORE_DRILL_RUN_MIGRATE !== "false";
|
||||
|
||||
async function httpCheck(path, headers = {}) {
|
||||
const response = await fetch(`${baseUrl}${path}`, { headers });
|
||||
const text = await response.text();
|
||||
let body = null;
|
||||
try {
|
||||
body = text ? JSON.parse(text) : null;
|
||||
} catch {
|
||||
body = text;
|
||||
}
|
||||
if (!response.ok) {
|
||||
throw new Error(`${path} failed status=${response.status} body=${text.slice(0, 200)}`);
|
||||
}
|
||||
return body?.data !== undefined ? body.data : body;
|
||||
}
|
||||
|
||||
async function dbCheck() {
|
||||
const pool = new Pool(
|
||||
process.env.DATABASE_URL
|
||||
? { connectionString: process.env.DATABASE_URL }
|
||||
: {
|
||||
host: process.env.PGHOST || "127.0.0.1",
|
||||
port: Number(process.env.PGPORT || 5432),
|
||||
user: process.env.PGUSER || "postgres",
|
||||
password: process.env.PGPASSWORD || "postgres",
|
||||
database: process.env.PGDATABASE || "qris_soundbox_platform"
|
||||
}
|
||||
);
|
||||
try {
|
||||
const tables = await pool.query(
|
||||
"SELECT table_name FROM information_schema.tables WHERE table_schema = 'public' AND table_name IN ('merchants','devices','transactions','export_jobs','schema_migrations')"
|
||||
);
|
||||
return tables.rows.map((row) => row.table_name).sort();
|
||||
} finally {
|
||||
await pool.end();
|
||||
}
|
||||
}
|
||||
|
||||
if (runMigrate) {
|
||||
const result = spawnSync("npm", ["run", "db:migrate"], { stdio: "inherit", env: process.env });
|
||||
if (result.status !== 0) {
|
||||
throw new Error(`db:migrate failed with status ${result.status}`);
|
||||
}
|
||||
}
|
||||
|
||||
const [health, adminHealth, tables] = await Promise.all([
|
||||
httpCheck("/health"),
|
||||
httpCheck("/admin/health/deep", { Authorization: `Bearer ${adminToken}` }),
|
||||
dbCheck()
|
||||
]);
|
||||
|
||||
console.log(
|
||||
JSON.stringify(
|
||||
{
|
||||
ok: true,
|
||||
base_url: baseUrl,
|
||||
health,
|
||||
admin_health_status: adminHealth.status,
|
||||
tables
|
||||
},
|
||||
null,
|
||||
2
|
||||
)
|
||||
);
|
||||
Reference in New Issue
Block a user