Skip to content

feat(queue): multi-queue preload cache, preload-N setting, manual preload - #76

Merged
Roboroads merged 3 commits into
mainfrom
feat/queue-multi-preload
Jun 25, 2026
Merged

feat(queue): multi-queue preload cache, preload-N setting, manual preload#76
Roboroads merged 3 commits into
mainfrom
feat/queue-multi-preload

Conversation

@Roboroads

@Roboroads Roboroads commented Jun 19, 2026

Copy link
Copy Markdown
Collaborator

Replaces the single-entry global preloader with one shared, path-keyed cache that holds the union of every queue's preload window, so multiple autoplaying queues no longer evict each other (fixes the CodeRabbit finding skipped on #69). Adds a per-queue "preload first N tracks" setting (default 1, with a RAM hint), a manual per-row preload button, and a one-time toast warning when the decoded cache exceeds 1 GB.

Closes #75.

Summary by CodeRabbit

  • New Features
    • Added configurable multi-track “preload window” for queue autoplay (1–20 tracks ahead).
    • Added per-track “preload into memory” and per-song preload indicators (spinner for preloading, bolt when ready).
    • Added RAM-aware monitoring with a one-time toast warning when cached audio exceeds 1GB.
  • Bug Fixes
    • Improved preload caching so tracks aren’t re-decoded unnecessarily, with correct eviction when they leave the active window.
    • Safeguarded against race conditions and stale updates from superseded decodes, including proper clear behavior after failures.
    • Preload count is now persisted and clamped to the 20-track maximum.

…load

Signed-off-by: Robbin "Roboroads" Schepers <robbin@deschepers.nl>
@Roboroads
Roboroads marked this pull request as ready for review June 19, 2026 17:22
@coderabbitai

coderabbitai Bot commented Jun 19, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: b5485214-5201-49f5-9269-5db909895ec1

📥 Commits

Reviewing files that changed from the base of the PR and between 25f56ba and f92ddd5.

📒 Files selected for processing (2)
  • packages/streamline/renderer/src/modules/queue/Queue.component.spec.ts
  • packages/streamline/renderer/src/modules/queue/Queue.svelte
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/streamline/renderer/src/modules/queue/Queue.svelte

📝 Walkthrough

Walkthrough

Replaces the single-entry TrackPreloader with a path-keyed multi-entry cache using an owner-window model (setWindow, releaseOwner, preloadManual, getStatus). Queue.svelte drives a configurable-length window of upcoming track paths, tracks per-path preload state per row, and adds a manual preload button. QueueSettingsModal gains a clamped numeric preloadCount input. A 1 GB decoded-bytes threshold emits a one-shot toast warning.

Changes

Multi-queue path-keyed preloader with window ownership, manual preload, and RAM guard

Layer / File(s) Summary
TrackPreloader contract, implementation, and tests
packages/streamline/renderer/src/audio/track-preload.ts, packages/streamline/renderer/src/audio/track-preload.spec.ts
PreloadStatePayload.path becomes non-nullable; TrackPreloader interface replaces preload with setWindow, preloadManual, releaseOwner, and getStatus. createTrackPreloader is rewritten with per-path cache entries, per-path decode generation guards, owner-window union aggregation, eviction/reconciliation, and RAM-threshold toast emission. Test helpers (fakeBuffer, deferredDecode) are refactored for windowed testing; the spec covers window-driven decode, cross-queue isolation, stale decode races, eviction, clearing, and RAM-warning cycles.
Queue multi-track preload window, manual preload, and per-row UI
packages/streamline/renderer/src/modules/queue/Queue.svelte, packages/streamline/renderer/src/modules/queue/Queue.component.spec.ts
QueueSettings adds preloadCount; a reactive derived window of upcoming paths is registered via setWindow on each autoplay update; per-path preload progress is tracked in a SvelteMap per row; the component releases its owner on destroy via releaseOwner; per-row controls branch on ready/preloading/neither with spinner, bolt action, or manual preload button. The spec adds a richer mockPreloader with explicit methods, tests manual-preload button interaction, fixes dragOver event sequencing, and validates preloadCount persistence and 20-track clamping.
QueueSettingsModal preloadCount prop, UI, wiring, and tests
packages/streamline/renderer/src/modules/queue/QueueSettingsModal.svelte, packages/streamline/renderer/src/modules/queue/QueueSettingsModal.component.spec.ts
QueueSettingsModal receives preloadCount and onPreloadCountChange props; renders a numeric input clamped to 1–20 tracks. Queue.svelte wires onPreloadCountChange to persist via updateSettings. All existing modal spec render calls are updated to supply the new props; a new test verifies clamped input behavior (4.6→5, 0→1).

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • StreamlineRadio/Streamline#69: Introduced the original single-entry track-preload.ts and TRACK_PRELOAD_STATE event mechanism that this PR directly replaces with the path-keyed multi-entry cache and window-ownership model.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately and concisely summarizes the three main changes: multi-queue preload cache, preload-N setting, and manual preload feature.
Linked Issues check ✅ Passed All four featured objectives from issue #75 are implemented: multi-queue safe preloader with shared path-keyed cache [#75], per-queue preload-N setting with default 1 [#75], manual preload functionality [#75], and RAM safety with 1GB warning [#75].
Out of Scope Changes check ✅ Passed All code changes directly support the linked issue requirements; no out-of-scope work detected. Changes are focused on preloading architecture, settings, UI indicators, and RAM monitoring.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/streamline/renderer/src/audio/track-preload.ts`:
- Around line 115-118: The setWindow method calls reconcile() synchronously on
line 117, which can evict paths before a same-tick take(path) call can claim
them, breaking the hand-off safety guarantee. Defer the reconcile() call in the
setWindow method to a microtask using queueMicrotask() instead of calling it
synchronously. Apply the same fix to the other synchronous reconcile() call
mentioned at lines 132-135 to ensure consistent microtask-deferred
reconciliation across all window update operations.

In `@packages/streamline/renderer/src/modules/queue/Queue.svelte`:
- Around line 83-86: The preloadCount derived value on line 83 only enforces a
minimum bound of 0 using Math.max, but does not enforce an upper bound on the
value from currentSettings.preloadCount. This allows malformed or oversized
settings values to create an unexpectedly large preload window and increase
decode pressure. Update the preloadCount derivation to clamp the value to both a
minimum of 0 and a reasonable maximum (such as the length of the items array or
a configurable limit) to ensure the JSON-derived settings are defensively
bounded at runtime before being used in the windowPaths calculation.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: b94ac32c-35ab-412a-ae1f-dc05210b9415

📥 Commits

Reviewing files that changed from the base of the PR and between 2293099 and 25f56ba.

📒 Files selected for processing (6)
  • packages/streamline/renderer/src/audio/track-preload.spec.ts
  • packages/streamline/renderer/src/audio/track-preload.ts
  • packages/streamline/renderer/src/modules/queue/Queue.component.spec.ts
  • packages/streamline/renderer/src/modules/queue/Queue.svelte
  • packages/streamline/renderer/src/modules/queue/QueueSettingsModal.component.spec.ts
  • packages/streamline/renderer/src/modules/queue/QueueSettingsModal.svelte

Comment thread packages/streamline/renderer/src/audio/track-preload.ts
Comment thread packages/streamline/renderer/src/modules/queue/Queue.svelte Outdated
Signed-off-by: Robbin "Roboroads" Schepers <robbin@deschepers.nl>
@Roboroads
Roboroads enabled auto-merge (squash) June 25, 2026 11:27
@Roboroads
Roboroads merged commit 160bd22 into main Jun 25, 2026
9 checks passed
@Roboroads
Roboroads deleted the feat/queue-multi-preload branch June 25, 2026 11:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Multi-queue preloading: shared path-keyed cache, per-queue preload-N setting, manual preload, RAM guard

1 participant