docs(quick-19): complete fix phantom playlist tracks plan
- Add 19-SUMMARY.md with execution results - Update STATE.md quick tasks table
This commit is contained in:
@@ -0,0 +1,100 @@
|
||||
---
|
||||
phase: quick-19
|
||||
plan: 19
|
||||
subsystem: playlist
|
||||
tags: [bugfix, multi-library, path-resolution]
|
||||
dependency_graph:
|
||||
requires: [Phase 10 schema, Phase 11 scan pipeline]
|
||||
provides: [multi-root M3U8 path resolution]
|
||||
affects: [playlist merge, playlist restore, phantom resolution]
|
||||
tech_stack:
|
||||
added: []
|
||||
patterns: [resolveM3UPath multi-root lookup, toRelativePathMultiRoot]
|
||||
key_files:
|
||||
created: []
|
||||
modified:
|
||||
- backend/playlist/m3u.go
|
||||
- backend/playlist/playlist.go
|
||||
- backend/playlist/m3u_test.go
|
||||
- backend/library/scan_queue.go
|
||||
decisions:
|
||||
- resolveM3UPath with knownPaths set for O(1) lookup instead of O(n) per-root DB queries
|
||||
- Import and restore use per-root DB queries since no pre-built path set available
|
||||
- toRelativePathMultiRoot picks first root that contains the path
|
||||
metrics:
|
||||
duration: 7 min
|
||||
completed: "2026-03-16"
|
||||
tasks: 2
|
||||
files: 4
|
||||
---
|
||||
|
||||
# Quick Task 19: Fix Phantom Playlist Tracks Summary
|
||||
|
||||
Multi-root M3U8 path resolution replacing single-library `getLibraryRoot()` with `getAllLibraryRoots()` across all playlist path operations.
|
||||
|
||||
## What Changed
|
||||
|
||||
### Task 1: Multi-root path resolution in m3u.go and playlist.go (9144ded)
|
||||
|
||||
**m3u.go — New functions:**
|
||||
- `resolveM3UPath(relativePath, libraryRoots, knownPaths)` — resolves a relative M3U path against multiple roots, returning the first absolute path found in the knownPaths set. Falls back to first root for phantom tracks.
|
||||
- `toRelativePathMultiRoot(absolutePath, libraryRoots)` — converts an absolute path to relative using the first root that contains it.
|
||||
|
||||
**m3u.go — Updated signatures:**
|
||||
- `removeM3UEntries` — `libraryRoot string` → `libraryRoots []string`
|
||||
- `replaceM3UEntryPaths` — `libraryRoot string` → `libraryRoots []string`
|
||||
- `findM3UEntry` — `libraryRoot string` → `libraryRoots []string`
|
||||
|
||||
**playlist.go — Core change:**
|
||||
- Replaced `getLibraryRoot() string` with `getAllLibraryRoots() []string` — queries all libraries from DB (or falls back to legacy config)
|
||||
|
||||
**playlist.go — 8 call sites updated:**
|
||||
1. `mergeTracksForPlaylist` — builds knownPaths set from dbTracks, uses resolveM3UPath
|
||||
2. `ImportPlaylist` — tries each root via GetAudioFileByPath until match found
|
||||
3. `RestoreAllPlaylists` — passes libraryRoots to restoreSinglePlaylist
|
||||
4. `restoreSinglePlaylist` — tries each root for each M3U8 entry
|
||||
5. `buildM3UEntries` — uses toRelativePathMultiRoot for correct relative paths per track
|
||||
6. `saveImportedPlaylistFile` — uses toRelativePathMultiRoot
|
||||
7. `FindPhantomMatches` — uses resolveM3UPath for entry lookup
|
||||
8. `GetPhantomCandidates` — passes libraryRoots to findM3UEntry
|
||||
9. `ResolvePhantomTracks` — uses toRelativePathMultiRoot and multi-root replaceM3UEntryPaths
|
||||
10. `RemovePhantomTracks` — passes libraryRoots to removeM3UEntries
|
||||
|
||||
### Task 2: Multi-root path resolution tests (a902850)
|
||||
|
||||
Added 5 new test functions with 20 test cases:
|
||||
- `TestResolveM3UPath` — 7 cases covering abs paths, multi-root resolution, fallback, nil/empty
|
||||
- `TestToRelativePathMultiRoot` — 5 cases covering first root, second root, no match, empty
|
||||
- `TestRemoveM3UEntriesMultiRoot` — entries from different roots correctly removed
|
||||
- `TestFindM3UEntryMultiRoot` — entry under second root found correctly
|
||||
- `TestReplaceM3UEntryPathsMultiRoot` — replacement under second root applied
|
||||
|
||||
Updated 5 existing tests for new `[]string` parameter types.
|
||||
|
||||
## Deviations from Plan
|
||||
|
||||
### Auto-fixed Issues
|
||||
|
||||
**1. [Rule 3 - Blocking] Pre-existing golines formatting in scan_queue.go**
|
||||
- **Found during:** Task 1 commit
|
||||
- **Issue:** `golangci-lint` pre-commit hook checks all Go files, not just staged; `scan_queue.go` had a line too long for golines
|
||||
- **Fix:** Split the SQL string literal across multiple lines
|
||||
- **Files modified:** backend/library/scan_queue.go
|
||||
- **Commit:** 9144ded (included in Task 1)
|
||||
|
||||
**2. [Rule 3 - Blocking] Existing tests use old single-root signatures**
|
||||
- **Found during:** Task 1
|
||||
- **Issue:** Changing function signatures broke existing test compilation, blocking the commit
|
||||
- **Fix:** Updated 5 existing test call sites from `string` to `[]string{...}` (merged into Task 1 instead of waiting for Task 2)
|
||||
- **Files modified:** backend/playlist/m3u_test.go
|
||||
- **Commit:** 9144ded
|
||||
|
||||
## Verification Results
|
||||
|
||||
- `go build ./backend/...` — PASS
|
||||
- `go vet ./backend/playlist/...` — PASS
|
||||
- `go test ./backend/playlist/...` — PASS (38 tests)
|
||||
- `go test ./backend/...` — PASS (all packages, no regressions)
|
||||
- `golangci-lint` — PASS (0 issues)
|
||||
|
||||
## Self-Check: PASSED
|
||||
Reference in New Issue
Block a user