Add DB migration for workflow_runs, album_events tables and cancelled download state

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/claude-agent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
Alexander
2026-05-11 15:53:27 +02:00
parent eab92dd40b
commit 7d11b729a5
2 changed files with 145 additions and 0 deletions
@@ -0,0 +1,112 @@
CREATE TYPE monitor_state AS ENUM ('unmonitored', 'monitored', 'excluded');
CREATE TYPE download_state AS ENUM ('pending', 'downloading', 'completed', 'failed', 'seeding');
CREATE TABLE artists (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
external_id VARCHAR(255) NOT NULL UNIQUE,
name VARCHAR(255) NOT NULL,
artist_type VARCHAR(50) NOT NULL,
country VARCHAR(10),
genres TEXT[] NOT NULL DEFAULT '{}',
image_url TEXT,
monitor_state monitor_state NOT NULL DEFAULT 'unmonitored',
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX idx_artists_monitor_state ON artists(monitor_state);
CREATE TABLE albums (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
external_id VARCHAR(255) NOT NULL UNIQUE,
artist_id UUID NOT NULL REFERENCES artists(id) ON DELETE CASCADE,
title VARCHAR(255) NOT NULL,
album_type VARCHAR(50) NOT NULL,
release_date DATE,
total_tracks INTEGER NOT NULL DEFAULT 0,
total_discs INTEGER NOT NULL DEFAULT 1,
label VARCHAR(255),
genres TEXT[] NOT NULL DEFAULT '{}',
cover_url TEXT,
monitor_state monitor_state NOT NULL DEFAULT 'unmonitored',
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX idx_albums_artist_id ON albums(artist_id);
CREATE INDEX idx_albums_monitor_state ON albums(monitor_state);
CREATE TABLE tracks (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
external_id VARCHAR(255) NOT NULL UNIQUE,
album_id UUID NOT NULL REFERENCES albums(id) ON DELETE CASCADE,
title VARCHAR(255) NOT NULL,
duration_ms INTEGER NOT NULL DEFAULT 0,
isrc VARCHAR(20),
disc_number INTEGER NOT NULL DEFAULT 1,
track_number INTEGER NOT NULL DEFAULT 1,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX idx_tracks_album_id ON tracks(album_id);
CREATE TABLE torrents (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
album_id UUID NOT NULL REFERENCES albums(id) ON DELETE CASCADE,
info_hash VARCHAR(64) NOT NULL UNIQUE,
tracker VARCHAR(100) NOT NULL,
title TEXT NOT NULL,
format VARCHAR(20) NOT NULL,
quality VARCHAR(20) NOT NULL,
source VARCHAR(50),
bit_depth INTEGER,
sample_rate INTEGER,
seeders INTEGER NOT NULL DEFAULT 0,
peers INTEGER NOT NULL DEFAULT 0,
size BIGINT NOT NULL DEFAULT 0,
track_count INTEGER NOT NULL DEFAULT 0,
has_cover_art BOOLEAN NOT NULL DEFAULT false,
has_cue_sheet BOOLEAN NOT NULL DEFAULT false,
has_rip_log BOOLEAN NOT NULL DEFAULT false,
download_link TEXT,
torrent_file BYTEA,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX idx_torrents_album_id ON torrents(album_id);
CREATE TABLE downloads (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
torrent_id UUID NOT NULL REFERENCES torrents(id) ON DELETE CASCADE,
album_id UUID NOT NULL REFERENCES albums(id) ON DELETE CASCADE,
format VARCHAR(20) NOT NULL,
quality VARCHAR(20) NOT NULL,
state download_state NOT NULL DEFAULT 'pending',
qbit_hash VARCHAR(64),
save_path TEXT,
error_message TEXT,
queued_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
started_at TIMESTAMPTZ,
completed_at TIMESTAMPTZ,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX idx_downloads_album_id ON downloads(album_id);
CREATE INDEX idx_downloads_torrent_id ON downloads(torrent_id);
CREATE INDEX idx_downloads_state ON downloads(state);
CREATE TABLE download_files (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
download_id UUID NOT NULL REFERENCES downloads(id) ON DELETE CASCADE,
track_id UUID REFERENCES tracks(id) ON DELETE SET NULL,
file_path TEXT NOT NULL,
file_size BIGINT NOT NULL DEFAULT 0,
file_type VARCHAR(50) NOT NULL,
sha256_hash VARCHAR(64),
verified_at TIMESTAMPTZ,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX idx_download_files_download_id ON download_files(download_id);
@@ -0,0 +1,33 @@
CREATE TABLE workflow_runs (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
album_id UUID NOT NULL REFERENCES albums(id) ON DELETE CASCADE,
quality VARCHAR(20) NOT NULL,
status VARCHAR(20) NOT NULL DEFAULT 'running',
error_message TEXT,
started_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
completed_at TIMESTAMPTZ,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
running_lock BOOLEAN GENERATED ALWAYS AS (CASE WHEN status = 'running' THEN TRUE ELSE NULL END) STORED,
CONSTRAINT idx_workflow_runs_active UNIQUE (album_id, quality, running_lock)
);
CREATE INDEX idx_workflow_runs_status ON workflow_runs(status);
CREATE TABLE album_events (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
seq BIGSERIAL NOT NULL,
workflow_run_id UUID NOT NULL REFERENCES workflow_runs(id) ON DELETE CASCADE,
album_id UUID NOT NULL,
event_type VARCHAR(20) NOT NULL,
step VARCHAR(50) NOT NULL,
message TEXT NOT NULL,
data_json JSONB,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX idx_album_events_workflow ON album_events(workflow_run_id);
CREATE INDEX idx_album_events_album ON album_events(album_id);
CREATE INDEX idx_album_events_seq ON album_events(seq);
ALTER TYPE download_state ADD VALUE IF NOT EXISTS 'cancelled';