mahdahar dc6cca71cf feat: move instrument onboarding to YAML config
Replace DB-backed instrument upserts with app.yaml-driven config loading, matching, and translator application in the ingestion workflow. Also add serial-port connector support, startup validation tooling, and migration tracking updates to keep runtime behavior and docs aligned.
2026-04-06 16:50:17 +07:00

84 lines
2.1 KiB
JavaScript

const fs = require('fs');
const path = require('path');
const DatabaseClient = require('./db');
const config = require('../../config/app');
const LOCK_MIGRATION_FILE = '002_outbox_locks.sql';
async function ensureMigrationTable(db) {
await db.exec(`
CREATE TABLE IF NOT EXISTS schema_migrations (
filename TEXT PRIMARY KEY,
applied_at TEXT NOT NULL DEFAULT (datetime('now'))
);
`);
}
async function migrationIsApplied(db, filename) {
const row = await db.get(
'SELECT filename FROM schema_migrations WHERE filename = ? LIMIT 1',
[filename]
);
return Boolean(row);
}
async function markMigrationApplied(db, filename) {
await db.run(
'INSERT OR IGNORE INTO schema_migrations (filename) VALUES (?)',
[filename]
);
}
async function applyOutboxLockMigration(db) {
const columns = await db.all('PRAGMA table_info(outbox_result)');
const columnNames = new Set(columns.map((column) => column.name));
if (!columnNames.has('locked_at')) {
await db.exec('ALTER TABLE outbox_result ADD COLUMN locked_at INTEGER NULL;');
}
if (!columnNames.has('locked_by')) {
await db.exec('ALTER TABLE outbox_result ADD COLUMN locked_by TEXT NULL;');
}
}
async function migrate() {
const db = new DatabaseClient(config.db);
const migrationsDir = path.join(__dirname, '..', '..', 'db', 'migrations');
const files = fs
.readdirSync(migrationsDir)
.filter((name) => name.endsWith('.sql'))
.sort();
await ensureMigrationTable(db);
for (const file of files) {
if (await migrationIsApplied(db, file)) {
continue;
}
if (file === LOCK_MIGRATION_FILE) {
await applyOutboxLockMigration(db);
await markMigrationApplied(db, file);
continue;
}
const payload = fs.readFileSync(path.join(migrationsDir, file), 'utf8');
await db.exec(payload);
await markMigrationApplied(db, file);
}
await db.close();
}
if (require.main === module) {
migrate()
.then(() => console.log('migrations applied'))
.catch((err) => {
console.error('migration failed', err);
process.exit(1);
});
}
module.exports = migrate;