Track details look a path up in the whole library, and do nothing when it is not loaded #279

Open
opened 2026-10-06 02:40:27 +00:00 by yonlu · 1 comment
Owner

Five places resolve a file path to a full library.Track by looking it up in the whole library's track array (libraryStore.getCachedTracks() / getTracks() through tracksByFilePath):

  • queue-panel openTrackDetails / openBatchTrackDetails
  • playlist-details openTrackDetails
  • smart-playlist-details openTrackDetails / openBatchTrackDetails
  • utils/track-details-opener.ts showTrackDetailsForPath (awaits a full GetTracks)
  • track-details after a save (getTracks() + .find)

Two consequences:

  1. It is a bug when the array is not loaded. The queue, playlist and smart-playlist openers use getCachedTracks() and return silently when it is null — "Track details" does nothing. Today that is masked only because library-store eagerly fetches every track at startup and after every invalidation.
  2. It is why the eager fetch exists. Opening one track's details costs the whole library (20.5 MB of JSON at 26 138 tracks, measured), so the only way to make it fast was to have paid for it already.

Reproduction (bug half)

Make getCachedTracks() return null (comment out this.eagerFetch() in deferEagerFetch, or open the queue during the first second after a rescan's invalidation), right-click a queue row → Track details: nothing opens, nothing is reported.

Proposed

GetTracksByPaths(paths) in backend/library, and a frontend track-cache keyed by file path: bounded LRUMap registered with cache-stats, requests coalesced to one binding call per frame, answers in caller order, cleared/patched by the same events library-store handles. Every opener above goes through it. A source sweep asserts nothing outside library-store and the Tracks view reads the whole-library array.

Part of the memory work measured on 2026-10-05 (plan 023).

Five places resolve a file path to a full `library.Track` by looking it up in **the whole library's track array** (`libraryStore.getCachedTracks()` / `getTracks()` through `tracksByFilePath`): - `queue-panel` `openTrackDetails` / `openBatchTrackDetails` - `playlist-details` `openTrackDetails` - `smart-playlist-details` `openTrackDetails` / `openBatchTrackDetails` - `utils/track-details-opener.ts` `showTrackDetailsForPath` (awaits a full `GetTracks`) - `track-details` after a save (`getTracks()` + `.find`) Two consequences: 1. **It is a bug when the array is not loaded.** The queue, playlist and smart-playlist openers use `getCachedTracks()` and `return` silently when it is `null` — "Track details" does nothing. Today that is masked only because `library-store` eagerly fetches every track at startup and after every invalidation. 2. **It is why the eager fetch exists.** Opening one track's details costs the whole library (20.5 MB of JSON at 26 138 tracks, measured), so the only way to make it fast was to have paid for it already. ### Reproduction (bug half) Make `getCachedTracks()` return null (comment out `this.eagerFetch()` in `deferEagerFetch`, or open the queue during the first second after a rescan's invalidation), right-click a queue row → Track details: nothing opens, nothing is reported. ### Proposed `GetTracksByPaths(paths)` in `backend/library`, and a frontend `track-cache` keyed by file path: bounded `LRUMap` registered with `cache-stats`, requests coalesced to one binding call per frame, answers in caller order, cleared/patched by the same events `library-store` handles. Every opener above goes through it. A source sweep asserts nothing outside `library-store` and the Tracks view reads the whole-library array. Part of the memory work measured on 2026-10-05 (plan 023).
yonlu self-assigned this 2026-10-06 02:40:40 +00:00
yonlu added the
Status
In Progress
label 2026-10-06 02:40:41 +00:00
Author
Owner

Plan 023 (scoped library payloads), in order 279 → 281 → 280 → 282, then 283 and 284. Measured before/after with make perf against the bulk seed.

Plan 023 (scoped library payloads), in order 279 → 281 → 280 → 282, then 283 and 284. Measured before/after with make perf against the bulk seed.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Reference: yonlu/yellowjacket#279