# Data Model Specification

This document defines the data schema across PostgreSQL (Primary), Typesense (Search), and Redis (Caching/Queueing).

## 1. Relational Schema (PostgreSQL)

### **Core Tables**

#### `tracks`
*   `id` (UUID, PK)
*   `path` (TEXT, UNIQUE) - Physical disk path.
*   `hash` (TEXT, INDEX) - BLOB/MD5 hash for deduplication.
*   `title`, `artist`, `album` (TEXT)
*   `duration` (REAL) - In seconds.
*   `state` (ENUM) - `[LIBRARY, RECOMMENDED, HIDDEN, MISSING, DELETED]`
*   `play_count`, `skip_count`, `dislike_count` (INTEGER)
*   `last_played_at` (TIMESTAMP)
*   `mtime` (REAL) - File mtime at last index.
*   `source_type` (ENUM) - `[MANUAL, RECOMMENDATION]`

#### `artists` & `albums`
*   `artists`: `id`, `name`, `mbid`, `discogs_id`, `image_path`.
*   `albums`: `id`, `artist_id`, `title`, `year`, `artwork_id`.

#### `genre` & `track_genre`
*   `genre`: `id`, `name`, `parent_id` (Self-join for hierarchy).
*   `track_genre`: `track_id`, `genre_id`, `weight` (Decimal).

### **Recommendation & Lifecycle Tables**

#### `recommendation_batch`
*   `id` (UUID, PK)
*   `user_id` (UUID)
*   `status` (ENUM) - `[ACTIVE, RESOLVED, FAILED]`
*   `last_interaction_at` (TIMESTAMP)
*   `seed_track_id` (UUID, FK)

#### `dislikes`
*   `track_id` (UUID, FK)
*   `disliked_at` (TIMESTAMP)
*   `warned_at` (TIMESTAMP, NULLABLE)
*   `state` (ENUM) - `[HIDDEN, WARNED, DELETED]`

### **Metadata & Enrichment**
*   `track_audio_features`: `track_id`, `bpm`, `key`, `energy`, `danceability`, etc.
*   `track_lyrics`: `track_id`, `lyrics_text`, `provider`.
*   `mb_cache` / `lastfm_cache`: Key-Value stores for external API responses.

## 2. Search Schema (Typesense)

Typesense is used for ultra-fast, fuzzy search. Indices are rebuilt from PostgreSQL.

**Index: `tracks`**
*   `title` (string, facet)
*   `artist` (string, facet)
*   `album` (string, facet)
*   `genres` (string, facet)
*   `state` (string, filterable)

## 3. Cache & Queue (Redis)

*   **BullMQ:** Stores job payloads and processing states.
*   **Session Cache:** Stores ephemeral playback metadata and current "rolling window" track IDs.
