@@ -47,7 +47,7 @@ if (!process.env.DATABASE && !isHeadlessProcess) {
4747const dbConnectionString = process . env . DATABASE ! ;
4848export const DatabaseType = isHeadlessProcess ? "postgres" : dbConnectionString . split ( ":" ) [ 0 ] ?. replace ( "+srv" , "" ) ;
4949const applyMigrations = process . env . APPLY_DB_MIGRATIONS !== "false" ;
50-
50+ const MIGRATIONLOCK = 1 ;
5151export const DataSourceOptions = isHeadlessProcess
5252 ? ( undefined as unknown as DataSource )
5353 : new DataSource ( {
@@ -109,19 +109,25 @@ export async function initDatabase(): Promise<DataSource> {
109109 }
110110 } ;
111111 if ( applyMigrations ) {
112+ const qr = dbConnection . createQueryRunner ( ) ;
113+ /*
114+ The transaction lock ensures that exactly one server is attempting to run migrations at a time.
115+ It is session-specific, so should be released if a crash occurs. It is also blocking, so all
116+ servers can run their logic.
117+ */
118+ await qr . query ( `Select pg_advisory_lock(${ MIGRATIONLOCK } )` ) ;
112119 if ( ! ( await dbExists ( ) ) ) {
113120 console . log ( "[Database] This appears to be a fresh database. Running initial DDL." ) ;
114- const qr = dbConnection . createQueryRunner ( ) ;
115121 const initialPath = path . join ( __dirname , "migration" , DatabaseType + "-initial.js" ) ;
116122 if ( fs . existsSync ( initialPath ) ) {
117123 console . log ( "[Database] Found initial migration file, running it." ) ;
118124 await new ( require ( `./migration/${ DatabaseType } -initial` ) . initial0 ) ( ) . up ( qr ) ;
119125 } else console . log ( "[Database] No initial migration file found at '" , initialPath , "', skipping." ) ;
120- await qr . release ( ) ;
121126 }
122-
123127 console . log ( "[Database] Applying missing migrations, if any." , process . env . APPLY_DB_MIGRATIONS ) ;
124128 await dbConnection . runMigrations ( ) ;
129+ await qr . query ( `Select pg_advisory_unlock(${ MIGRATIONLOCK } )` ) ;
130+ await qr . release ( ) ;
125131 } else {
126132 console . log ( "[Database] Skipping migrations as per config." ) ;
127133 while ( ! ( await dbExists ( ) ) ) {
0 commit comments