Log fatal migration context
Browse files- src/server.js +3 -0
- src/utils/migrate.js +33 -5
src/server.js
CHANGED
|
@@ -14,6 +14,9 @@ async function start() {
|
|
| 14 |
await runMigrations();
|
| 15 |
} catch (err) {
|
| 16 |
console.error('[Boot] Migration failed — aborting:', err.message);
|
|
|
|
|
|
|
|
|
|
| 17 |
process.exit(1);
|
| 18 |
}
|
| 19 |
|
|
|
|
| 14 |
await runMigrations();
|
| 15 |
} catch (err) {
|
| 16 |
console.error('[Boot] Migration failed — aborting:', err.message);
|
| 17 |
+
if (err.migrationContext) {
|
| 18 |
+
console.error('[Boot] Migration context:', JSON.stringify(err.migrationContext));
|
| 19 |
+
}
|
| 20 |
process.exit(1);
|
| 21 |
}
|
| 22 |
|
src/utils/migrate.js
CHANGED
|
@@ -406,9 +406,28 @@ function repairBlockingMariaArtifacts() {
|
|
| 406 |
return repaired;
|
| 407 |
}
|
| 408 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 409 |
async function runMigrations() {
|
| 410 |
console.log('[migrate] Running schema migrations...');
|
| 411 |
-
for (
|
|
|
|
| 412 |
const targetTable = extractTargetTable(sql);
|
| 413 |
try {
|
| 414 |
await db.query(sql);
|
|
@@ -426,11 +445,20 @@ async function runMigrations() {
|
|
| 426 |
console.warn(`[migrate] Skipping already-satisfied migration after MariaDB alter failure: ${col}`);
|
| 427 |
} else if (err.errno === 21 && repairBlockingMariaArtifacts()) {
|
| 428 |
console.warn(`[migrate] Retrying after artifact repair for table ${targetTable}`);
|
| 429 |
-
|
| 430 |
-
|
| 431 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 432 |
} else {
|
| 433 |
-
|
|
|
|
|
|
|
| 434 |
throw err;
|
| 435 |
}
|
| 436 |
}
|
|
|
|
| 406 |
return repaired;
|
| 407 |
}
|
| 408 |
|
| 409 |
+
function buildMigrationFailureContext(index, sql, table, err) {
|
| 410 |
+
return {
|
| 411 |
+
index,
|
| 412 |
+
targetTable: table,
|
| 413 |
+
errno: err?.errno ?? null,
|
| 414 |
+
code: err?.code ?? null,
|
| 415 |
+
sqlState: err?.sqlState ?? null,
|
| 416 |
+
message: err?.message ?? null,
|
| 417 |
+
sql: summarizeSql(sql),
|
| 418 |
+
dbDir: DB_DIR,
|
| 419 |
+
dbDirExists: fs.existsSync(DB_DIR),
|
| 420 |
+
};
|
| 421 |
+
}
|
| 422 |
+
|
| 423 |
+
function logFatalMigrationFailure(context) {
|
| 424 |
+
console.error('[migration-error] Fatal migration failure:', JSON.stringify(context));
|
| 425 |
+
}
|
| 426 |
+
|
| 427 |
async function runMigrations() {
|
| 428 |
console.log('[migrate] Running schema migrations...');
|
| 429 |
+
for (let i = 0; i < migrations.length; i += 1) {
|
| 430 |
+
const sql = migrations[i];
|
| 431 |
const targetTable = extractTargetTable(sql);
|
| 432 |
try {
|
| 433 |
await db.query(sql);
|
|
|
|
| 445 |
console.warn(`[migrate] Skipping already-satisfied migration after MariaDB alter failure: ${col}`);
|
| 446 |
} else if (err.errno === 21 && repairBlockingMariaArtifacts()) {
|
| 447 |
console.warn(`[migrate] Retrying after artifact repair for table ${targetTable}`);
|
| 448 |
+
try {
|
| 449 |
+
await db.query(sql);
|
| 450 |
+
const col = sql.match(/(?:ADD|MODIFY) COLUMN (\w+)/i)?.[1] ?? sql.slice(0, 60);
|
| 451 |
+
console.log(`[migrate] Applied after repair: ${col}`);
|
| 452 |
+
} catch (retryErr) {
|
| 453 |
+
const context = buildMigrationFailureContext(i + 1, sql, targetTable, retryErr);
|
| 454 |
+
retryErr.migrationContext = context;
|
| 455 |
+
logFatalMigrationFailure(context);
|
| 456 |
+
throw retryErr;
|
| 457 |
+
}
|
| 458 |
} else {
|
| 459 |
+
const context = buildMigrationFailureContext(i + 1, sql, targetTable, err);
|
| 460 |
+
err.migrationContext = context;
|
| 461 |
+
logFatalMigrationFailure(context);
|
| 462 |
throw err;
|
| 463 |
}
|
| 464 |
}
|