Last active
October 31, 2021 17:15
-
-
Save TheRusskiy/94a767ff0e6b5116c3b22f266b655829 to your computer and use it in GitHub Desktop.
Typeorm - migrations with advisory lock
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { migrateDatabase } from './typeormMigrationUtills' | |
;(async () => { | |
await migrateDatabase() | |
})() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { syncDatabase } from './typeormMigrationUtills' | |
;(async () => { | |
await syncDatabase() | |
})() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Connection, createConnection } from 'typeorm' | |
import config from '../ormconfig' | |
import CRC32 from 'crc-32' | |
const MIGRATOR_SALT = 2053462845 | |
async function withAdvisoryLock( | |
connection: Connection, | |
callback: () => Promise<void> | |
): Promise<boolean> { | |
// generate a unique lock name, has to be an integer | |
const lockName = CRC32.str(config.database as string) * MIGRATOR_SALT | |
let lock = false | |
try { | |
// try to acquire a lock | |
const [{ pg_try_advisory_lock: locked }]: [ | |
{ pg_try_advisory_lock: boolean } | |
] = await connection.manager.query( | |
`SELECT pg_try_advisory_lock(${lockName})` | |
) | |
lock = locked | |
// if already locked, print a warning an exit | |
if (!lock) { | |
console.warn(`Failed to get advisory lock: ${lockName}`) | |
return false | |
} | |
// execute our code inside the lock | |
await callback() | |
return true | |
} finally { | |
// if we acquired a lock, we need to unlock it | |
if (lock) { | |
const [{ pg_advisory_unlock: wasLocked }]: [ | |
{ pg_advisory_unlock: boolean } | |
] = await connection.manager.query( | |
`SELECT pg_advisory_unlock(${lockName})` | |
) | |
if (!wasLocked) { | |
console.warn(`Advisory lock was not locked: ${lockName}`) | |
} | |
} | |
} | |
} | |
export async function migrateDatabase() { | |
const connection = await createConnection({ ...config, logging: true }) | |
await withAdvisoryLock(connection, async () => { | |
await connection.runMigrations({ | |
transaction: 'all' | |
}) | |
}) | |
await connection.close() | |
} | |
export async function syncDatabase() { | |
const connection = await createConnection({ ...config, logging: true }) | |
await withAdvisoryLock(connection, async () => { | |
await connection.synchronize() | |
}) | |
await connection.close() | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment