Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1ad0f28f48 |
+11
-5
@@ -12,14 +12,20 @@ Postgres and S3-compatible storage. The recommended OSS-friendly stack:
|
|||||||
## 1. Database (Neon)
|
## 1. Database (Neon)
|
||||||
|
|
||||||
1. Create a Neon project; copy the pooled connection string.
|
1. Create a Neon project; copy the pooled connection string.
|
||||||
2. Apply migrations (from CI/CD or locally):
|
2. Migrations run **automatically before every Railway deploy**: the repo's
|
||||||
|
`railway.json` sets `npm run db:migrate` as the pre-deploy command, which
|
||||||
|
Railway executes (with the service's env, so `DATABASE_URL` is present)
|
||||||
|
before starting the new deployment. Re-running is a no-op for anything
|
||||||
|
already applied, and concurrent runs (api + worker deploying off the same
|
||||||
|
push) serialize on a Postgres advisory lock. A failed migration fails the
|
||||||
|
deploy — the old version keeps serving.
|
||||||
|
|
||||||
|
To apply migrations manually (first-time setup, or outside Railway):
|
||||||
```bash
|
```bash
|
||||||
DATABASE_URL='postgres://...neon.../ditto_site?sslmode=require' npm run db:migrate
|
DATABASE_URL='postgres://...neon.../ditto_site?sslmode=require' npm run db:migrate
|
||||||
```
|
```
|
||||||
Run this on every deploy that changes `packages/db/migrations`. Drizzle tracks
|
(Alternatively, apply a single migration by piping its SQL through
|
||||||
applied migrations in the database, so re-running is a no-op for anything
|
`psql`/the Neon CLI — but prefer `db:migrate`, which also records the
|
||||||
already applied. (Alternatively, apply a single migration by piping its SQL
|
|
||||||
through `psql`/the Neon CLI — but prefer `db:migrate`, which also records the
|
|
||||||
journal entry so future runs stay consistent.)
|
journal entry so future runs stay consistent.)
|
||||||
|
|
||||||
Current migrations: `0000` core tables, `0001` signup tokens,
|
Current migrations: `0000` core tables, `0001` signup tokens,
|
||||||
|
|||||||
@@ -6,12 +6,26 @@ import { createDb } from "./client.js";
|
|||||||
const HERE = dirname(fileURLToPath(import.meta.url));
|
const HERE = dirname(fileURLToPath(import.meta.url));
|
||||||
export const MIGRATIONS_DIR = join(HERE, "..", "migrations");
|
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> {
|
export async function runMigrations(connectionString: string, migrationsFolder = MIGRATIONS_DIR): Promise<void> {
|
||||||
const { db, pool } = createDb(connectionString);
|
const { db, pool } = createDb(connectionString);
|
||||||
|
const client = await pool.connect();
|
||||||
|
try {
|
||||||
|
await client.query("SELECT pg_advisory_lock($1)", [MIGRATE_LOCK_ID]);
|
||||||
try {
|
try {
|
||||||
await migrate(db, { migrationsFolder });
|
await migrate(db, { migrationsFolder });
|
||||||
} finally {
|
} finally {
|
||||||
|
await client.query("SELECT pg_advisory_unlock($1)", [MIGRATE_LOCK_ID]);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
client.release();
|
||||||
await pool.end();
|
await pool.end();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://railway.com/railway.schema.json",
|
||||||
|
"deploy": {
|
||||||
|
"preDeployCommand": "npm run db:migrate"
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user