77 lines
1.5 KiB
JavaScript
77 lines
1.5 KiB
JavaScript
const db = require("./db");
|
|
const migrations = require("./migrations");
|
|
|
|
function sleep(ms) {
|
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
}
|
|
|
|
async function waitForDatabase({
|
|
retries = 30,
|
|
delayMs = 2000,
|
|
} = {}) {
|
|
let lastError;
|
|
|
|
for (let attempt = 1; attempt <= retries; attempt++) {
|
|
try {
|
|
await db.query("SELECT 1");
|
|
return;
|
|
} catch (error) {
|
|
lastError = error;
|
|
|
|
console.log(`Database not ready yet (${attempt}/${retries})`);
|
|
|
|
if (attempt < retries) {
|
|
await sleep(delayMs);
|
|
}
|
|
}
|
|
}
|
|
|
|
throw lastError;
|
|
}
|
|
|
|
async function ensureMigrationsTable() {
|
|
await db.query(`
|
|
CREATE TABLE IF NOT EXISTS schema_migrations (
|
|
id VARCHAR(255) PRIMARY KEY,
|
|
applied_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
)
|
|
`);
|
|
}
|
|
|
|
async function getAppliedMigrationIds() {
|
|
const [rows] = await db.query(`
|
|
SELECT id
|
|
FROM schema_migrations
|
|
ORDER BY id ASC
|
|
`);
|
|
|
|
return new Set(rows.map((row) => row.id));
|
|
}
|
|
|
|
async function runMigrations() {
|
|
await waitForDatabase();
|
|
await ensureMigrationsTable();
|
|
|
|
const appliedIds = await getAppliedMigrationIds();
|
|
|
|
for (const migration of migrations) {
|
|
if (appliedIds.has(migration.id)) {
|
|
continue;
|
|
}
|
|
|
|
console.log(`Running migration ${migration.id}`);
|
|
|
|
await migration.up(db);
|
|
|
|
await db.query(
|
|
"INSERT INTO schema_migrations (id) VALUES (?)",
|
|
[migration.id]
|
|
);
|
|
}
|
|
}
|
|
|
|
module.exports = {
|
|
runMigrations,
|
|
waitForDatabase,
|
|
};
|