This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
/**
|
||||
* Builds the composite index SiteEvent_sessionId_timestamp_idx on the
|
||||
* SiteEvent table using CREATE INDEX CONCURRENTLY.
|
||||
*
|
||||
* Must connect via the non-pooler (direct) Neon URL because:
|
||||
* - CREATE INDEX CONCURRENTLY cannot run inside a transaction
|
||||
* - The pooler enforces statement_timeout that overrides SET
|
||||
*
|
||||
* Usage:
|
||||
* DIRECT_URL="postgres://..." node scripts/build-sessionid-index.mjs
|
||||
*
|
||||
* Never hardcode credentials here. Supply DIRECT_URL from the shell only.
|
||||
*/
|
||||
|
||||
import pkg from "pg";
|
||||
const { Client } = pkg;
|
||||
|
||||
const INDEX_NAME = "SiteEvent_sessionId_timestamp_idx";
|
||||
|
||||
const directUrl = process.env.DIRECT_URL;
|
||||
if (!directUrl) {
|
||||
console.error("[build-index] DIRECT_URL is not set. Aborting.");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const client = new Client({ connectionString: directUrl });
|
||||
|
||||
async function run() {
|
||||
console.log("[build-index] Connecting via DIRECT_URL...");
|
||||
await client.connect();
|
||||
console.log("[build-index] Connected.");
|
||||
|
||||
console.log("[build-index] SET statement_timeout = 0");
|
||||
await client.query("SET statement_timeout = 0;");
|
||||
|
||||
console.log("[build-index] SET lock_timeout = 0");
|
||||
await client.query("SET lock_timeout = 0;");
|
||||
|
||||
console.log(`[build-index] DROP INDEX IF EXISTS "${INDEX_NAME}"`);
|
||||
await client.query(`DROP INDEX IF EXISTS "${INDEX_NAME}";`);
|
||||
console.log("[build-index] Drop complete (or index did not exist).");
|
||||
|
||||
console.log(`[build-index] CREATE INDEX CONCURRENTLY "${INDEX_NAME}" -- this may take several minutes on large tables`);
|
||||
await client.query(
|
||||
`CREATE INDEX CONCURRENTLY "${INDEX_NAME}" ON "public"."SiteEvent" ("sessionId", "timestamp");`,
|
||||
);
|
||||
console.log("[build-index] Index build complete.");
|
||||
|
||||
const res = await client.query(
|
||||
`SELECT indisvalid
|
||||
FROM pg_index
|
||||
JOIN pg_class ON pg_class.oid = pg_index.indexrelid
|
||||
WHERE pg_class.relname = $1;`,
|
||||
[INDEX_NAME],
|
||||
);
|
||||
|
||||
if (res.rows.length === 0) {
|
||||
console.error("[build-index] Index not found after creation -- something went wrong.");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const { indisvalid } = res.rows[0];
|
||||
if (indisvalid) {
|
||||
console.log("[build-index] indisvalid = true -- index is VALID and ready.");
|
||||
} else {
|
||||
console.error("[build-index] indisvalid = false -- index is INVALID. Manual cleanup required.");
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
run()
|
||||
.catch((err) => {
|
||||
console.error("[build-index] Fatal error:", err.message);
|
||||
process.exit(1);
|
||||
})
|
||||
.finally(() => {
|
||||
client.end().catch(() => {});
|
||||
});
|
||||
Reference in New Issue
Block a user