Skip to content

fix(ios): bound large native playback queues - #266

Open
luwux wants to merge 1 commit into
ghenry22:masterfrom
luwux:codex/fix-ios-large-queue-stall
Open

fix(ios): bound large native playback queues#266
luwux wants to merge 1 commit into
ghenry22:masterfrom
luwux:codex/fix-ios-large-queue-stall

Conversation

@luwux

@luwux luwux commented Aug 7, 2026

Copy link
Copy Markdown

Summary

  • keep the complete logical playback queue while bounding the iOS gapless AVQueuePlayer to a 32-item forward window
  • replenish the native window after auto-advance and queue mutations
  • remove a duplicate full-tail AVPlayerItem build on non-preserving queue sync
  • add a credential-free iOS regression test for 1,527 logical queue positions

Why

Starting a song from a large list could make the entire iOS UI unresponsive for several seconds even though the loading animation continued. On a 1,527-song Favorites list, a Search tap sent 100 ms after the song tap was still unapplied 6.497 seconds later.

Native instrumentation showed that RNQP performed two eager full-tail AVPlayerItem builds and then inserted 1,515 items into AVQueuePlayer synchronously on the main actor. The complete operation occupied the main actor for 9.646–21.799 seconds in measured runs; the insertion loop alone took 3.4–11.7 seconds.

The full queue already has an authoritative logical owner in QueueState. Gapless playback only needs the current item plus a bounded forward window, so this change avoids materialising thousands of native items while preserving queue semantics. Crossfade keeps its existing full snapshot because its indexed transitions depend on it.

Verification

  • reproduced the baseline freeze on iPhone 17 Pro / iOS 26.5 Simulator with 1,527 songs
  • after the patch, Search and Settings taps sent 100 ms after a song tap were accepted in the first captured state (0.887 s / 0.839 s including automation capture overhead)
  • advanced 35 tracks to verify replenishment beyond the initial 32-item window
  • npm run test:ios-large-queue (5 focused tests)
  • RNQP iOS XCTest suite (611 tests)
  • npx tsc --noEmit
  • npx jest --no-coverage (404 suites / 7,048 tests)
  • iOS Simulator Release build

Public demo

The official Navidrome Demo contains 501 songs. In an isolated read-only baseline run, Search and Settings actions sent while playback was still In progress were accepted, returning about 1.19 s and 1.16 s after dispatch and appearing selected in the first captured state. This did not reproduce the multi-second unresponsive interval measured at 1,527 songs, so the Demo is a compatibility check rather than a reliable reproducer. Shared favorites were not modified.

Closes #244

@luwux
luwux marked this pull request as ready for review August 10, 2026 05:51
Keep the complete logical queue while materialising only a forward AVQueuePlayer window, replenishing it as playback advances. This avoids building and inserting thousands of AVPlayerItems on the main thread.

Closes ghenry22#244
@luwux
luwux force-pushed the codex/fix-ios-large-queue-stall branch from ff911e2 to eb3c084 Compare August 18, 2026 18:52
@luwux

luwux commented Aug 18, 2026

Copy link
Copy Markdown
Author

Hi, I wanted to add a brief note about the user impact and the current validation status.

Without this fix, large Favorites lists are effectively unusable on iOS: tapping a track can make the entire app unresponsive for more than ten seconds before playback begins. This severely affects a core playback workflow and the overall user experience.

I have rebased this PR onto the latest master and revalidated it there. The focused large-queue regression tests, the complete RNQP iOS XCTest suite (611 tests), TypeScript checks, the complete Jest suite (534 suites / 9,404 tests), and an iOS Simulator Release build all pass.

Given the impact, I would be very grateful if this could be reviewed and merged, or otherwise addressed, as soon as practical. Thank you very much for your time and for maintaining the project.

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.

Long loading times and constant app freezes

1 participant