diff --git a/src/core/db.ts b/src/core/db.ts index 36b4a6c..69f8ecd 100644 --- a/src/core/db.ts +++ b/src/core/db.ts @@ -60,7 +60,13 @@ export async function disconnect(): Promise { export async function initSchema(): Promise { const conn = getConnection(); - await conn.unsafe(SCHEMA_SQL); + // Advisory lock prevents concurrent initSchema() calls from deadlocking + await conn`SELECT pg_advisory_lock(42)`; + try { + await conn.unsafe(SCHEMA_SQL); + } finally { + await conn`SELECT pg_advisory_unlock(42)`; + } } export async function withTransaction(fn: (tx: ReturnType) => Promise): Promise { diff --git a/src/core/postgres-engine.ts b/src/core/postgres-engine.ts index eb9ca7c..c1332f6 100644 --- a/src/core/postgres-engine.ts +++ b/src/core/postgres-engine.ts @@ -57,12 +57,19 @@ export class PostgresEngine implements BrainEngine { async initSchema(): Promise { const conn = this.sql; - await conn.unsafe(SCHEMA_SQL); + // Advisory lock prevents concurrent initSchema() calls from deadlocking + // on DDL statements (DROP TRIGGER + CREATE TRIGGER acquire AccessExclusiveLock) + await conn`SELECT pg_advisory_lock(42)`; + try { + await conn.unsafe(SCHEMA_SQL); - // Run any pending migrations automatically - const { applied } = await runMigrations(this); - if (applied > 0) { - console.log(` ${applied} migration(s) applied`); + // Run any pending migrations automatically + const { applied } = await runMigrations(this); + if (applied > 0) { + console.log(` ${applied} migration(s) applied`); + } + } finally { + await conn`SELECT pg_advisory_unlock(42)`; } }