- SUMMARY.md with 2 task commits, 6 files, 6 requirements completed - STATE.md advanced to Phase 12 Plan 1/2, added Phase 12 decisions - ROADMAP.md marked 12-01 complete (1/2 plans) - REQUIREMENTS.md marked LIB-01, LIB-02, LIB-03, DATA-02, DATA-03, PLAY-04 complete
7.3 KiB
7.3 KiB
phase, plan, subsystem, tags, requires, provides, affects, tech-stack, key-files, key-decisions, patterns-established, requirements-completed, duration, completed
| phase | plan | subsystem | tags | requires | provides | affects | tech-stack | key-files | key-decisions | patterns-established | requirements-completed | duration | completed | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 12-library-crud-data-integrity | 01 | library |
|
|
|
|
|
|
|
|
|
6min | 2026-03-12 |
Phase 12 Plan 01: Library CRUD Backend API Summary
Backend CRUD API with AddLibrary/RenameLibrary/RemoveLibrary, full orphan cleanup pipeline, phantom track preservation, FTS5 rebuild, queue compaction, and event emission
Performance
- Duration: 6 min
- Started: 2026-03-12T23:32:27Z
- Completed: 2026-03-12T23:38:30Z
- Tasks: 2
- Files created: 1
- Files modified: 5
Accomplishments
- AddLibrary(path) — validates path exists, auto-names from folder base, creates DB row via sqlc, emits LibraryAdded, starts async ScanLibrary
- RenameLibrary(id, newName) — validates 1-50 char length, checks name uniqueness across all libraries (application-level), updates via sqlc, emits LibraryRenamed
- GetRemovalImpact(libraryID) — read-only queries returning track count, affected playlists count, queue items count for confirmation dialog
- RemoveLibrary(id) — the critical 23-step method:
- Cancel active scan for library
- Stop playback if current track belongs to library
- Pre-count metrics for summary
- Begin transaction
- Populate phantom metadata on playlist_tracks (BEFORE cascade delete)
- DELETE audio_files WHERE library_id (CASCADE on queue_tracks, SET NULL on playlist_tracks)
- Bottom-up orphan cleanup: recordings → recording_genres → release_group_recordings → release_groups → artist_credits (dual FK check) → artist_credit_artists → artists → genres → cover_art
- DELETE library row
- Commit transaction
- Post-commit: RebuildSearchIndex (FTS5), delete cover art files, CompactQueue, emit events
- CompactAfterLibraryRemoval() on Queue — reloads surviving tracks from DB, detects if current track survived, resets index, unloads player if needed, clears shuffle order, emits QueueChanged
- RemovalHooks wired in app.go: StopPlayback → player.UnloadTrack(), CompactQueue → queue.CompactAfterLibraryRemoval()
- Three new event constants: LibraryAdded, LibraryRenamed, LibraryRemoved — auto-generated to frontend events.ts
Task Commits
Each task was committed atomically:
- Task 1: Implement Library CRUD methods and orphan cleanup pipeline —
bd44f83(feat)- Created backend/library/crud.go (525 lines) with all CRUD methods
- Added 3 event constants to backend/events/events.go
- Added removalHooks field to Library struct
- Regenerated frontend/src/events.ts
- Task 2: Add queue compaction method and wire removal hooks in app.go —
5995dfd(feat)- Added CompactAfterLibraryRemoval() to backend/queue/queue.go (80 lines)
- Wired RemovalHooks in backend/app.go OnStartup
Files Created/Modified
backend/library/crud.go(NEW) — AddLibrary, RenameLibrary, RemoveLibrary, GetRemovalImpact, cancelLibraryScan, currentTrackBelongsToLibrary, querySingleInt64, RemovalHooks type, sentinel errorsbackend/library/library.go— Added removalHooks RemovalHooks field to Library structbackend/events/events.go— Added LibraryAdded, LibraryRenamed, LibraryRemoved constantsfrontend/src/events.ts— Regenerated with new library CRUD event constantsbackend/queue/queue.go— Added CompactAfterLibraryRemoval methodbackend/app.go— Wired RemovalHooks in OnStartup (StopPlayback + CompactQueue callbacks)
Decisions Made
- Application-level name uniqueness: Iterate GetAllLibraries to check for duplicate names rather than adding a UNIQUE constraint to the libraries table. Avoids needing migration 7; the check is only done during rename which is infrequent.
- RemovalHooks callback struct: Follows the existing RescanHooks pattern to break circular dependencies between library → player and library → queue packages. Wired in app.go where all subsystems are accessible.
- querySingleInt64 helper: The project's
database.DBtype exposesQueryContextreturning*sql.Rowsbut noQueryRowContext. The helper wraps the full scan-close cycle for single-value aggregate queries. - Sentinel errors per err113: Defined
errLibraryNameEmpty,errLibraryNameTooLong,errLibraryNameDuplicate,errLibraryPathNotExistas package-level vars to satisfy the golangci-lint err113 rule. - Context-first parameter order:
querySingleInt64(ctx, db, query, args...)followsrevivelinter's context-as-argument rule.
Deviations from Plan
None — plan executed exactly as written.
Issues Encountered
None.
User Setup Required
None — no external service configuration required.
Next Plan Readiness
- Plan 12-01 complete — backend CRUD API fully implemented
- Ready for Plan 12-02: Frontend library management UI in settings + sidebar cleanup
- All Wails-bindable methods (AddLibrary, RenameLibrary, RemoveLibrary, GetRemovalImpact) are available for frontend consumption
- Events (LibraryAdded, LibraryRenamed, LibraryRemoved) are defined for frontend reactive updates
Self-Check: PASSED
All files verified present, all commits verified in git log.
Phase: 12-library-crud-data-integrity Completed: 2026-03-12