starry / backend /omr-service /src /db /migrate.ts
k-l-lambda's picture
Initial deployment: frontend + omr-service + cluster-server + nginx proxy
6f1c297
import { pool } from './client.js';
const migrations = [
{
name: '001_create_scores_table',
sql: `
CREATE TABLE IF NOT EXISTS scores (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
title VARCHAR(255),
source_url TEXT,
page_count INTEGER DEFAULT 0,
data JSONB DEFAULT '{}',
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
CREATE INDEX IF NOT EXISTS idx_scores_created_at ON scores(created_at DESC);
`,
},
{
name: '002_create_tasks_table',
sql: `
CREATE TYPE task_status AS ENUM ('pending', 'running', 'completed', 'failed');
CREATE TYPE task_type AS ENUM ('predict_page', 'predict_all', 'predict_custom');
CREATE TABLE IF NOT EXISTS tasks (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
score_id UUID REFERENCES scores(id) ON DELETE CASCADE,
type task_type NOT NULL,
status task_status DEFAULT 'pending',
progress INTEGER DEFAULT 0,
current_step VARCHAR(100),
result JSONB,
error TEXT,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
started_at TIMESTAMP WITH TIME ZONE,
completed_at TIMESTAMP WITH TIME ZONE
);
CREATE INDEX IF NOT EXISTS idx_tasks_score_id ON tasks(score_id);
CREATE INDEX IF NOT EXISTS idx_tasks_status ON tasks(status);
`,
},
{
name: '003_create_pages_table',
sql: `
CREATE TABLE IF NOT EXISTS pages (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
score_id UUID REFERENCES scores(id) ON DELETE CASCADE,
page_index INTEGER NOT NULL,
image_path TEXT,
width INTEGER,
height INTEGER,
data JSONB DEFAULT '{}',
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
UNIQUE(score_id, page_index)
);
CREATE INDEX IF NOT EXISTS idx_pages_score_id ON pages(score_id);
`,
},
{
name: '004_create_music_sets_table',
sql: `
CREATE TABLE IF NOT EXISTS music_sets (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name VARCHAR(255),
type VARCHAR(20) DEFAULT 'stave',
content JSONB DEFAULT '{}',
status VARCHAR(50) DEFAULT 'draft',
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
CREATE INDEX IF NOT EXISTS idx_music_sets_updated_at ON music_sets(updated_at DESC);
CREATE INDEX IF NOT EXISTS idx_music_sets_name ON music_sets(name);
`,
},
{
name: '005_create_tags_table',
sql: `
CREATE TABLE IF NOT EXISTS tags (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name VARCHAR(100) NOT NULL UNIQUE,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
CREATE TABLE IF NOT EXISTS music_set_tags (
music_set_id UUID REFERENCES music_sets(id) ON DELETE CASCADE,
tag_id UUID REFERENCES tags(id) ON DELETE CASCADE,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
PRIMARY KEY (music_set_id, tag_id)
);
CREATE INDEX IF NOT EXISTS idx_music_set_tags_music_set_id ON music_set_tags(music_set_id);
CREATE INDEX IF NOT EXISTS idx_music_set_tags_tag_id ON music_set_tags(tag_id);
`,
},
{
name: '006_create_solution_cache_table',
sql: `
CREATE TABLE IF NOT EXISTS solution_cache (
name VARCHAR(64) PRIMARY KEY,
value JSONB NOT NULL,
priority DOUBLE PRECISION,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
`,
},
{
name: '007_create_issue_measures_table',
sql: `
CREATE TABLE IF NOT EXISTS issue_measures (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
score_id VARCHAR(255) NOT NULL,
measure_index INTEGER NOT NULL,
measure JSONB NOT NULL,
status INTEGER NOT NULL DEFAULT 1,
by_user BOOLEAN DEFAULT false,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
CREATE INDEX IF NOT EXISTS idx_issue_measures_score_id ON issue_measures(score_id);
CREATE UNIQUE INDEX IF NOT EXISTS idx_issue_measures_score_measure
ON issue_measures(score_id, measure_index) WHERE status > 0;
`,
},
{
name: '008_add_annotator_to_issue_measures',
sql: `
ALTER TABLE issue_measures ADD COLUMN IF NOT EXISTS annotator VARCHAR(100);
`,
},
];
async function runMigrations() {
console.log('Running migrations...');
// Create migrations tracking table
await pool.query(`
CREATE TABLE IF NOT EXISTS migrations (
name VARCHAR(255) PRIMARY KEY,
executed_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
)
`);
for (const migration of migrations) {
const { rows } = await pool.query('SELECT name FROM migrations WHERE name = $1', [migration.name]);
if (rows.length === 0) {
console.log(`Running migration: ${migration.name}`);
await pool.query(migration.sql);
await pool.query('INSERT INTO migrations (name) VALUES ($1)', [migration.name]);
console.log(`Completed: ${migration.name}`);
} else {
console.log(`Skipping: ${migration.name} (already executed)`);
}
}
console.log('All migrations completed.');
}
runMigrations()
.then(() => process.exit(0))
.catch((err) => {
console.error('Migration failed:', err);
process.exit(1);
});