fix: add transaction wrapping and SQL splitter documentation in migrate.ts
Each migration file now runs in a transaction - if any statement fails, the entire file is rolled back and no _migrations record is written. Also documents the naive semicolon-split constraint. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
602dc3d098
commit
5dce775dce
1 changed files with 17 additions and 6 deletions
|
|
@ -11,7 +11,7 @@ export async function runMigrations(pool: Pool): Promise<void> {
|
|||
CREATE TABLE IF NOT EXISTS _migrations (
|
||||
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
|
||||
filename VARCHAR(255) NOT NULL UNIQUE,
|
||||
run_at DATETIME DEFAULT NOW()
|
||||
run_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||
)
|
||||
`);
|
||||
|
||||
|
|
@ -28,16 +28,27 @@ export async function runMigrations(pool: Pool): Promise<void> {
|
|||
if (rows.length > 0) continue;
|
||||
|
||||
const sql = fs.readFileSync(path.join(MIGRATIONS_DIR, file), "utf-8");
|
||||
// NOTE: This splitter is intentionally naive — migration files must not
|
||||
// contain semicolons inside string literals or block comments.
|
||||
const statements = sql
|
||||
.split(";")
|
||||
.map((s) => s.trim())
|
||||
.filter((s) => s.length > 0 && !s.startsWith("--"));
|
||||
|
||||
const conn = await pool.getConnection();
|
||||
await conn.beginTransaction();
|
||||
try {
|
||||
for (const stmt of statements) {
|
||||
await pool.execute(stmt);
|
||||
await conn.execute(stmt);
|
||||
}
|
||||
|
||||
await pool.execute("INSERT INTO _migrations (filename) VALUES (?)", [file]);
|
||||
await conn.execute("INSERT INTO _migrations (filename) VALUES (?)", [file]);
|
||||
await conn.commit();
|
||||
console.log(`Migration applied: ${file}`);
|
||||
} catch (err) {
|
||||
await conn.rollback();
|
||||
throw err;
|
||||
} finally {
|
||||
conn.release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue