fix(db): replace DROP-based reset with TRUNCATE RESTART IDENTITY CASCADE
GRO-2722: packages/db/src/reset.ts and apps/api/src/db/reset.ts no longer emit any DROP TABLE / DROP TYPE / DROP SCHEMA / DROP DATABASE DDL. The four destructive DO-blocks are replaced with a single: TRUNCATE <all public tables> RESTART IDENTITY CASCADE Table names are enumerated dynamically via pg_tables WHERE schemaname='public' so new tables are picked up automatically. The drizzle schema and __drizzle_migrations table are untouched (different schema), keeping drizzle-kit migrate a no-op on an already-migrated DB. Preserves: production guard (NODE_ENV=production && ALLOW_RESET!='true'), advisory lock, migrations (drizzle-kit migrate), and seed (runSeedBody). Fixes the GRO-2678 prod outage root cause. Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
+30
-36
@@ -1,10 +1,17 @@
|
||||
/**
|
||||
* reset.ts — Drop all application tables and re-run migrations + seed.
|
||||
* reset.ts — Truncate all public tables and restart identity sequences.
|
||||
*
|
||||
* Intended for local development only. Never run against production.
|
||||
* Schema-safe: never issues destructive DDL against any schema.
|
||||
* The drizzle schema and __drizzle_migrations table are preserved so
|
||||
* drizzle-kit migrate remains a no-op on an already-migrated DB.
|
||||
*
|
||||
* NOTE: this file is NOT the deployed reset entrypoint — the reset image
|
||||
* builds from packages/db and runs `pnpm --filter @groombook/db reset`.
|
||||
* apps/api db:reset delegates there too (see apps/api/package.json).
|
||||
* Keep in sync with packages/db/src/reset.ts (GRO-2722).
|
||||
*
|
||||
* Usage:
|
||||
* DATABASE_URL=postgres://... npx tsx packages/db/src/reset.ts
|
||||
* DATABASE_URL=postgres://... npx tsx apps/api/src/db/reset.ts
|
||||
*/
|
||||
|
||||
import postgres from "postgres";
|
||||
@@ -23,43 +30,30 @@ async function reset() {
|
||||
|
||||
const client = postgres(url, { max: 1 });
|
||||
|
||||
console.log("Dropping all application tables...\n");
|
||||
console.log("Truncating all public tables...\n");
|
||||
|
||||
// Drop in dependency order (children before parents)
|
||||
await client`
|
||||
DO $$ DECLARE
|
||||
r RECORD;
|
||||
BEGIN
|
||||
FOR r IN (
|
||||
SELECT tablename FROM pg_tables
|
||||
WHERE schemaname = 'public'
|
||||
) LOOP
|
||||
EXECUTE 'DROP TABLE IF EXISTS public.' || quote_ident(r.tablename) || ' CASCADE';
|
||||
END LOOP;
|
||||
END $$;
|
||||
// Enumerate all base tables in the public schema dynamically, then
|
||||
// issue a single TRUNCATE with RESTART IDENTITY CASCADE so FK cycles
|
||||
// are not a problem. The drizzle schema and __drizzle_migrations are
|
||||
// intentionally excluded (different schema) so drizzle-kit migrate
|
||||
// stays a no-op on an already-migrated DB.
|
||||
const tables = await client<{ tablename: string }[]>`
|
||||
SELECT tablename FROM pg_tables
|
||||
WHERE schemaname = 'public'
|
||||
`;
|
||||
|
||||
// Drop custom enums
|
||||
await client`
|
||||
DO $$ DECLARE
|
||||
r RECORD;
|
||||
BEGIN
|
||||
FOR r IN (
|
||||
SELECT typname FROM pg_type
|
||||
WHERE typtype = 'e' AND typnamespace = (
|
||||
SELECT oid FROM pg_namespace WHERE nspname = 'public'
|
||||
)
|
||||
) LOOP
|
||||
EXECUTE 'DROP TYPE IF EXISTS ' || quote_ident(r.typname) || ' CASCADE';
|
||||
END LOOP;
|
||||
END $$;
|
||||
`;
|
||||
if (tables.length > 0) {
|
||||
// Double-quote each identifier (escaping embedded quotes) to handle
|
||||
// any table name safely without a pg-specific quote_ident helper.
|
||||
const tableList = tables
|
||||
.map((t) => `"${t.tablename.replace(/"/g, '""')}"`)
|
||||
.join(", ");
|
||||
await client.unsafe(
|
||||
`TRUNCATE ${tableList} RESTART IDENTITY CASCADE`,
|
||||
);
|
||||
}
|
||||
|
||||
// Drop the drizzle migrations tracking table
|
||||
await client`DROP TABLE IF EXISTS drizzle.__drizzle_migrations CASCADE`;
|
||||
await client`DROP SCHEMA IF EXISTS drizzle CASCADE`;
|
||||
|
||||
console.log("✓ All tables and enums dropped\n");
|
||||
console.log("✓ All public tables truncated, sequences reset\n");
|
||||
|
||||
await client.end();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user