Run db:migrate automatically before every Railway deploy
The 2026-07-06 prod outage was a missed manual migration: the 0002 job_events migration never ran against prod, so the worker crash-looped on every job. Make the deploy pipeline own it: - railway.json sets `npm run db:migrate` as the pre-deploy command. Railway runs it with the service's env before starting the new deployment; a failed migration fails the deploy and the old version keeps serving. - runMigrations() now serializes on a Postgres advisory lock so api and worker pre-deploys firing off the same push can't race Drizzle's journal writes. - DEPLOY.md: document the automatic path; keep the manual command for first-time setup. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
5285ddc2b2
commit
1ad0f28f48
@@ -6,12 +6,26 @@ import { createDb } from "./client.js";
|
||||
const HERE = dirname(fileURLToPath(import.meta.url));
|
||||
export const MIGRATIONS_DIR = join(HERE, "..", "migrations");
|
||||
|
||||
/** Apply all pending Drizzle migrations to the target database. */
|
||||
/** App-wide advisory lock id for migrations. Concurrent `db:migrate` runs (e.g.
|
||||
* api + worker pre-deploy firing off the same push) serialize on it instead of
|
||||
* racing Drizzle's journal writes. */
|
||||
const MIGRATE_LOCK_ID = 0xd1770;
|
||||
|
||||
/** Apply all pending Drizzle migrations to the target database. Safe to run
|
||||
* concurrently: callers serialize on a Postgres advisory lock, and re-running
|
||||
* applied migrations is a journal no-op. */
|
||||
export async function runMigrations(connectionString: string, migrationsFolder = MIGRATIONS_DIR): Promise<void> {
|
||||
const { db, pool } = createDb(connectionString);
|
||||
const client = await pool.connect();
|
||||
try {
|
||||
await migrate(db, { migrationsFolder });
|
||||
await client.query("SELECT pg_advisory_lock($1)", [MIGRATE_LOCK_ID]);
|
||||
try {
|
||||
await migrate(db, { migrationsFolder });
|
||||
} finally {
|
||||
await client.query("SELECT pg_advisory_unlock($1)", [MIGRATE_LOCK_ID]);
|
||||
}
|
||||
} finally {
|
||||
client.release();
|
||||
await pool.end();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user