Add NixOS module for full agregators stack with VM test
Module manages PostgreSQL (both databases + schema init), qBittorrent (VPN-confined via VPN-Confinement), Jackett, metadata-agregator, musicfs, and the main orchestrator. All services are independently enableable with auto-wired inter-service configuration. Includes NixOS VM test validating PostgreSQL setup, schema initialization, service startup, and directory creation. Ultraworked with [Sisyphus](https://github.com/code-yeongyu/claude-agent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
@@ -0,0 +1,166 @@
|
||||
CREATE TYPE monitor_state AS ENUM ('monitored', 'unmonitored', 'excluded');
|
||||
|
||||
CREATE TABLE artists (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
external_id VARCHAR(255) NOT NULL UNIQUE,
|
||||
name VARCHAR(500) NOT NULL,
|
||||
artist_type VARCHAR(50),
|
||||
country VARCHAR(10),
|
||||
genres TEXT[],
|
||||
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 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(500) NOT NULL,
|
||||
album_type VARCHAR(50),
|
||||
release_date DATE,
|
||||
total_tracks INT,
|
||||
total_discs INT DEFAULT 1,
|
||||
label VARCHAR(255),
|
||||
genres TEXT[],
|
||||
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 ON albums(artist_id);
|
||||
CREATE INDEX idx_albums_monitored ON albums(monitor_state) WHERE monitor_state = 'monitored';
|
||||
|
||||
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(500) NOT NULL,
|
||||
duration_ms INT,
|
||||
isrc VARCHAR(20),
|
||||
disc_number INT DEFAULT 1,
|
||||
track_number INT NOT NULL,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
CREATE INDEX idx_tracks_album 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(40) NOT NULL UNIQUE,
|
||||
tracker VARCHAR(100) NOT NULL,
|
||||
title TEXT NOT NULL,
|
||||
format VARCHAR(20) NOT NULL,
|
||||
quality VARCHAR(20),
|
||||
source VARCHAR(20),
|
||||
bit_depth INT,
|
||||
sample_rate INT,
|
||||
seeders INT DEFAULT 0,
|
||||
peers INT DEFAULT 0,
|
||||
size BIGINT,
|
||||
track_count INT,
|
||||
has_cover_art BOOLEAN DEFAULT FALSE,
|
||||
has_cue_sheet BOOLEAN DEFAULT FALSE,
|
||||
has_rip_log BOOLEAN 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 ON torrents(album_id);
|
||||
CREATE INDEX idx_torrents_album_format ON torrents(album_id, format);
|
||||
|
||||
CREATE TYPE download_state AS ENUM (
|
||||
'pending', 'downloading', 'completed', 'failed', 'seeding', 'paused'
|
||||
);
|
||||
|
||||
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,
|
||||
format VARCHAR(20) NOT NULL,
|
||||
quality VARCHAR(20),
|
||||
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 UNIQUE INDEX idx_unique_active_torrent
|
||||
ON downloads(torrent_id)
|
||||
WHERE state NOT IN ('failed');
|
||||
|
||||
CREATE UNIQUE INDEX idx_unique_owned_album_quality
|
||||
ON downloads(album_id, format, quality)
|
||||
WHERE state IN ('completed', 'seeding');
|
||||
|
||||
CREATE INDEX idx_downloads_state ON downloads(state);
|
||||
CREATE INDEX idx_downloads_album ON downloads(album_id);
|
||||
|
||||
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),
|
||||
file_path TEXT NOT NULL,
|
||||
file_size BIGINT NOT NULL,
|
||||
file_type VARCHAR(20) NOT NULL,
|
||||
sha256_hash VARCHAR(64),
|
||||
verified_at TIMESTAMPTZ,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
CREATE INDEX idx_download_files_download ON download_files(download_id);
|
||||
CREATE INDEX idx_download_files_hash ON download_files(sha256_hash) WHERE sha256_hash IS NOT NULL;
|
||||
|
||||
CREATE TABLE album_releases (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
album_id UUID NOT NULL REFERENCES albums(id) ON DELETE CASCADE,
|
||||
download_id UUID NOT NULL REFERENCES downloads(id) ON DELETE CASCADE,
|
||||
format VARCHAR(20) NOT NULL,
|
||||
bit_depth INT,
|
||||
sample_rate INT,
|
||||
channels INT DEFAULT 2,
|
||||
is_lossless BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
source VARCHAR(20),
|
||||
total_size BIGINT NOT NULL DEFAULT 0,
|
||||
total_duration_ms INT NOT NULL DEFAULT 0,
|
||||
track_count INT NOT NULL DEFAULT 0,
|
||||
has_cover_art BOOLEAN DEFAULT FALSE,
|
||||
has_cue_sheet BOOLEAN DEFAULT FALSE,
|
||||
has_rip_log BOOLEAN DEFAULT FALSE,
|
||||
path TEXT NOT NULL,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
CREATE INDEX idx_album_releases_album ON album_releases(album_id);
|
||||
CREATE UNIQUE INDEX idx_album_releases_download ON album_releases(download_id);
|
||||
|
||||
CREATE TABLE track_releases (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
album_release_id UUID NOT NULL REFERENCES album_releases(id) ON DELETE CASCADE,
|
||||
track_id UUID REFERENCES tracks(id),
|
||||
download_file_id UUID REFERENCES download_files(id),
|
||||
title VARCHAR(500) NOT NULL,
|
||||
track_number INT NOT NULL DEFAULT 1,
|
||||
disc_number INT NOT NULL DEFAULT 1,
|
||||
duration_ms INT,
|
||||
format VARCHAR(20) NOT NULL,
|
||||
bit_depth INT,
|
||||
sample_rate INT,
|
||||
channels INT DEFAULT 2,
|
||||
bitrate_kbps INT,
|
||||
file_size BIGINT NOT NULL DEFAULT 0,
|
||||
file_path TEXT NOT NULL,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
CREATE INDEX idx_track_releases_album_release ON track_releases(album_release_id);
|
||||
Reference in New Issue
Block a user