Self-hosted web interface and downloader for Qobuz.

refactor(library): back library index with sqlite-direct library_tracks cache #48

Open glerp.sullen.net
targeting v1 from glerp.sullen.net/gobuz:refactor/library-sqlite-cache
Open opened by and assigned to glerp.sullen.net
targeting v1 from glerp.sullen.net/gobuz:refactor/library-sqlite-cache

Replaces the in-memory Library mirror (DirCache, Snapshot, TrackReader) and auxiliary library tables (release_provenance, release_owners, library_sidecar_covers) with a single rebuildable library_tracks SQLite cache table queried directly over WAL reader pools.

Stack Overview #

  • CL 1 (mnysnsnt) — refactor(config,store,models): enforce startup folder invariants and track-only library schema
    • Makes (Config).ResolveFolders() fail fast on missing/non-directory AuxDir entries, duplicate resolved roots, or nested/overlapping folder paths, resolving root symlinks once via filepath.EvalSymlinks while preserving :ro (default) and :rw AuxDir suffixes.
    • Replaces release_provenance, release_owners, and library_sidecar_covers in schemaV1 and PurgeCache with library_tracks (track_id primary key + 7 lookup indexes).
    • Adds LocalTrackID and ReleaseKey to models.LibraryTrack, and adds ReleaseKey, RouteID(), and unabbreviated CoverModifiedTime to models.LibraryRelease.
  • CL 2 (qpopzlmu) — refactor(library): back library index with sqlite-direct library_tracks cache
    • Rebuilds internal/library atop *store.DB (GetRelease, ListReleases, ListReleasesByDirectory, DeleteRelease, GetReleaseCover, MatchTrack, Scan, ScanFiles, Ready, Folders, and ThumbnailCache).
    • Derives 4-tier ReleaseKey (qobuz:<id>, mb:<uuid>, upc:<gtin>, tag:<24-hex>) purely from embedded audio tags via incremental (mtime_ns, size_bytes) worker-pool scans, ignoring symlinks inside music folders and failing fast if any configured root folder is inaccessible.
    • Resolves and validates sidecar covers (cover.{jpg,jpeg,png}) on demand in exclusive release/parent directories before falling back to embedded cover extraction, and prunes orphaned sidecars/booklet.pdf/empty subdirectories upward stopping strictly below folder_path on DeleteRelease.
    • Updates internal/web/library (removing bulk /library/delete-all, keying ThumbnailCache on ReleaseKey + CoverModifiedTime), internal/web/catalog (controller-local per-ReleaseKey Goosefoot import lock + multi-release directory 409 Conflict guard + post-import Scan), internal/playlist/resolver, internal/web/pages, and internal/web/server (ReleaseDeleted thumbnail invalidation).
Commits 2

refactor(library): back library index with sqlite-direct library_tracks cache
refactor(config,store,models): enforce startup folder invariants and track-only library schema