Backend Go: - Remplacement complet des anciennes migrations par la base V1 alignée sur ORIGIN. - Durcissement global du parsing JSON (BindAndValidateJSON + RespondWithAppError). - Sécurisation de config.go, CORS, statuts de santé et monitoring. - Implémentation des transactions P0 (RBAC, duplication de playlists, social toggles). - Ajout d’un job worker structuré (emails, analytics, thumbnails) + tests associés. - Nouvelle doc backend : AUDIT_CONFIG, BACKEND_CONFIG, AUTH_PASSWORD_RESET, JOB_WORKER_*. Chat server (Rust): - Refonte du pipeline JWT + sécurité, audit et rate limiting avancé. - Implémentation complète du cycle de message (read receipts, delivered, edit/delete, typing). - Nettoyage des panics, gestion d’erreurs robuste, logs structurés. - Migrations chat alignées sur le schéma UUID et nouvelles features. Stream server (Rust): - Refonte du moteur de streaming (encoding pipeline + HLS) et des modules core. - Transactions P0 pour les jobs et segments, garanties d’atomicité. - Documentation détaillée de la pipeline (AUDIT_STREAM_*, DESIGN_STREAM_PIPELINE, TRANSACTIONS_P0_IMPLEMENTATION). Documentation & audits: - TRIAGE.md et AUDIT_STABILITY.md à jour avec l’état réel des 3 services. - Cartographie complète des migrations et des transactions (DB_MIGRATIONS_*, DB_TRANSACTION_PLAN, AUDIT_DB_TRANSACTIONS, TRANSACTION_TESTS_PHASE3). - Scripts de reset et de cleanup pour la lab DB et la V1. Ce commit fige l’ensemble du travail de stabilisation P0 (UUID, backend, chat et stream) avant les phases suivantes (Coherence Guardian, WS hardening, etc.).
202 lines
No EOL
7.4 KiB
SQL
202 lines
No EOL
7.4 KiB
SQL
-- 040_streaming_core.sql
|
|
-- Core Streaming Entities: Tracks, Playlists (Aligned with ORIGIN)
|
|
|
|
-- === TRACKS ===
|
|
CREATE TABLE public.tracks (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
creator_id UUID NOT NULL REFERENCES public.users(id) ON DELETE CASCADE,
|
|
file_id UUID NOT NULL REFERENCES public.files(id) ON DELETE RESTRICT,
|
|
|
|
-- Track Info
|
|
title VARCHAR(255) NOT NULL,
|
|
description TEXT,
|
|
artist VARCHAR(255),
|
|
album VARCHAR(255),
|
|
genre VARCHAR(100),
|
|
|
|
-- Audio Properties
|
|
duration INTEGER NOT NULL, -- seconds
|
|
bpm INTEGER,
|
|
musical_key VARCHAR(10),
|
|
|
|
-- Visibility
|
|
visibility public.visibility NOT NULL DEFAULT 'public',
|
|
is_downloadable BOOLEAN NOT NULL DEFAULT false,
|
|
|
|
-- Media
|
|
cover_art_file_id UUID REFERENCES public.files(id) ON DELETE SET NULL,
|
|
waveform_data JSONB,
|
|
|
|
-- Counts (denormalized)
|
|
play_count INTEGER NOT NULL DEFAULT 0,
|
|
like_count INTEGER NOT NULL DEFAULT 0,
|
|
comment_count INTEGER NOT NULL DEFAULT 0,
|
|
download_count INTEGER NOT NULL DEFAULT 0,
|
|
|
|
-- Legacy/Go Compatibility fields (Denormalized or Mapped)
|
|
user_id UUID, -- Maps to creator_id
|
|
file_path VARCHAR(500), -- Maps to files.url or storage_path
|
|
file_size BIGINT, -- Maps to files.file_size
|
|
format VARCHAR(10),
|
|
bitrate INTEGER,
|
|
sample_rate INTEGER,
|
|
waveform_path VARCHAR(500), -- Legacy
|
|
cover_art_path VARCHAR(500), -- Legacy
|
|
status VARCHAR(20) DEFAULT 'uploading', -- Legacy status
|
|
status_message TEXT,
|
|
is_public BOOLEAN DEFAULT true, -- Maps to visibility='public'
|
|
|
|
-- Timestamps
|
|
published_at TIMESTAMPTZ,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
deleted_at TIMESTAMPTZ,
|
|
|
|
CONSTRAINT chk_tracks_duration_positive CHECK (duration > 0)
|
|
);
|
|
|
|
-- Indexes
|
|
CREATE INDEX idx_tracks_creator_id ON public.tracks(creator_id);
|
|
CREATE INDEX idx_tracks_genre ON public.tracks(genre);
|
|
CREATE INDEX idx_tracks_visibility ON public.tracks(visibility);
|
|
CREATE INDEX idx_tracks_published_at_desc ON public.tracks(published_at DESC) WHERE published_at IS NOT NULL;
|
|
CREATE INDEX idx_tracks_play_count_desc ON public.tracks(play_count DESC);
|
|
CREATE INDEX idx_tracks_created_at_desc ON public.tracks(created_at DESC);
|
|
CREATE INDEX idx_tracks_search_gin ON public.tracks USING GIN(to_tsvector('english', title || ' ' || COALESCE(artist, '') || ' ' || COALESCE(album, '')));
|
|
|
|
-- === TRACK VERSIONS (Legacy/Go Support) ===
|
|
-- Origin doesn't strictly specify this, but code implies it. Keeping minimal.
|
|
CREATE TABLE public.track_versions (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
track_id UUID NOT NULL REFERENCES public.tracks(id) ON DELETE CASCADE,
|
|
|
|
version_number INTEGER NOT NULL,
|
|
file_path VARCHAR(500) NOT NULL,
|
|
file_size BIGINT NOT NULL,
|
|
changelog TEXT,
|
|
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
deleted_at TIMESTAMPTZ
|
|
);
|
|
|
|
CREATE INDEX idx_track_versions_track_id ON public.track_versions(track_id);
|
|
CREATE INDEX idx_track_versions_created_at ON public.track_versions(created_at DESC);
|
|
|
|
-- === PLAYLISTS ===
|
|
CREATE TABLE public.playlists (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
user_id UUID NOT NULL REFERENCES public.users(id) ON DELETE CASCADE,
|
|
|
|
-- Playlist Info
|
|
name VARCHAR(255) NOT NULL,
|
|
description TEXT,
|
|
|
|
-- Media
|
|
cover_url TEXT,
|
|
|
|
-- Properties
|
|
visibility public.visibility NOT NULL DEFAULT 'public',
|
|
is_collaborative BOOLEAN NOT NULL DEFAULT false,
|
|
|
|
-- Counts
|
|
track_count INTEGER NOT NULL DEFAULT 0,
|
|
duration_seconds INTEGER NOT NULL DEFAULT 0,
|
|
follower_count INTEGER NOT NULL DEFAULT 0,
|
|
|
|
-- Legacy
|
|
title VARCHAR(200), -- Maps to name
|
|
is_public BOOLEAN DEFAULT true, -- Maps to visibility
|
|
|
|
-- Timestamps
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
deleted_at TIMESTAMPTZ
|
|
);
|
|
|
|
-- Indexes
|
|
CREATE INDEX idx_playlists_user_id ON public.playlists(user_id);
|
|
CREATE INDEX idx_playlists_visibility ON public.playlists(visibility);
|
|
CREATE INDEX idx_playlists_created_at_desc ON public.playlists(created_at DESC);
|
|
|
|
-- === PLAYLIST TRACKS (Junction) ===
|
|
CREATE TABLE public.playlist_tracks (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
playlist_id UUID NOT NULL REFERENCES public.playlists(id) ON DELETE CASCADE,
|
|
track_id UUID NOT NULL REFERENCES public.tracks(id) ON DELETE CASCADE,
|
|
|
|
-- Order
|
|
position INTEGER NOT NULL,
|
|
|
|
-- Metadata
|
|
added_by UUID NOT NULL REFERENCES public.users(id) ON DELETE CASCADE,
|
|
added_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
|
|
CONSTRAINT uq_playlist_tracks_playlist_track UNIQUE (playlist_id, track_id)
|
|
);
|
|
|
|
CREATE INDEX idx_playlist_tracks_playlist_id_position ON public.playlist_tracks(playlist_id, position);
|
|
CREATE INDEX idx_playlist_tracks_track_id ON public.playlist_tracks(track_id);
|
|
CREATE INDEX idx_playlist_tracks_added_by ON public.playlist_tracks(added_by);
|
|
|
|
-- === PLAYLIST COLLABORATORS (Legacy/Lab) ===
|
|
CREATE TABLE public.playlist_collaborators (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
playlist_id UUID NOT NULL REFERENCES public.playlists(id) ON DELETE CASCADE,
|
|
user_id UUID NOT NULL REFERENCES public.users(id) ON DELETE CASCADE,
|
|
|
|
permission public.playlist_permission NOT NULL DEFAULT 'read',
|
|
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
deleted_at TIMESTAMPTZ
|
|
);
|
|
|
|
CREATE INDEX idx_playlist_collaborators_playlist_id ON public.playlist_collaborators(playlist_id);
|
|
CREATE INDEX idx_playlist_collaborators_user_id ON public.playlist_collaborators(user_id);
|
|
|
|
-- === PLAYLIST FOLLOWS (Legacy/Lab - likely covered by 'follows' or custom logic) ===
|
|
CREATE TABLE public.playlist_follows (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
playlist_id UUID NOT NULL REFERENCES public.playlists(id) ON DELETE CASCADE,
|
|
user_id UUID NOT NULL REFERENCES public.users(id) ON DELETE CASCADE,
|
|
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
deleted_at TIMESTAMPTZ
|
|
);
|
|
|
|
CREATE INDEX idx_playlist_follows_playlist_id ON public.playlist_follows(playlist_id);
|
|
CREATE INDEX idx_playlist_follows_user_id ON public.playlist_follows(user_id);
|
|
|
|
-- === QUEUES ===
|
|
CREATE TABLE public.queues (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
user_id UUID NOT NULL REFERENCES public.users(id) ON DELETE CASCADE UNIQUE,
|
|
|
|
-- Current Track
|
|
current_track_id UUID REFERENCES public.tracks(id) ON DELETE SET NULL,
|
|
current_position INTEGER NOT NULL DEFAULT 0,
|
|
|
|
-- Playback State
|
|
is_playing BOOLEAN NOT NULL DEFAULT false,
|
|
shuffle BOOLEAN NOT NULL DEFAULT false,
|
|
repeat_mode VARCHAR(20) NOT NULL DEFAULT 'off',
|
|
volume INTEGER NOT NULL DEFAULT 100,
|
|
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
CREATE UNIQUE INDEX idx_queues_user_id ON public.queues(user_id);
|
|
|
|
-- === QUEUE ITEMS ===
|
|
CREATE TABLE public.queue_items (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
queue_id UUID NOT NULL REFERENCES public.queues(id) ON DELETE CASCADE,
|
|
track_id UUID NOT NULL REFERENCES public.tracks(id) ON DELETE CASCADE,
|
|
|
|
position INTEGER NOT NULL,
|
|
added_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
CREATE INDEX idx_queue_items_queue_id_position ON public.queue_items(queue_id, position); |