Skip to content

Keep retrying when a reconnect's initial request fails - #143

Open
romansorochak wants to merge 2 commits into
dimitris-c:mainfrom
StarGoApps:fix/retry-after-failed-reconnect-header-upstream
Open

romansorochak wants to merge 2 commits into
dimitris-c:mainfrom
StarGoApps:fix/retry-after-failed-reconnect-header-upstream

Conversation

@romansorochak

Copy link
Copy Markdown
Contributor

Problem

After a dropped stream, retryOnError() reopens the source through seek(at:) → performOpen → initialRequest. That is a bytes=0-1 request, and its callback handles only .response. If the request fails because the server or the network is still down a second after the drop, the .stream(.failure) event falls through default: break. No stream request starts and no retry is scheduled, so playback stays in buffering until the user does something. The Retrier is idle at that point, because its callback's seek already cancelled it, and nothing calls it again.

Fix

Send the initial request's failure through handleFailedStreamEvent, the same path the stream's own failures take. The source then keeps retrying, or waits for the network, until a reconnect succeeds. The change is 5 lines in RemoteAudioSource.swift.

Test

New RemoteAudioSourceRetryTests. A loopback NWListener cuts the stream mid-body and then refuses connections for 1.5 s.

  • Without the fix: no audio arrives from a later connection, and the test times out at 10 s.
  • With the fix: it passes 5 of 5 runs, about 2 s each.

swift test: Executed 60 tests, with 0 failures.

We also saw this in our app: with a server that drops the stream and refuses connections for 3 s, the player stayed in Loading indefinitely before this change, and with it the player reconnects at +3 s and plays.

romansorochak and others added 2 commits October 14, 2026 01:00
After a dropped stream, retryOnError() reopens the source through
seek(at:) -> performOpen -> initialRequest, a bytes=0-1 request whose
callback only handled .response. If that request failed - the server or
network still down a second after the drop - the .stream(.failure)
event fell through `default: break`: no stream request was started and
no retry was scheduled, so playback stayed in buffering until the user
acted. The Retrier itself is idle at that point (its callback's seek
already cancelled it); nothing called it again.

Route the initial request's failure through handleFailedStreamEvent, the
same path the stream's own failures take, so the source keeps retrying
(or waits for the network) until a reconnect succeeds.

The new RemoteAudioSourceRetryTests drives a loopback server that cuts
the stream mid-body and refuses connections for 1.5 s after it; without
this change no audio arrives from a later connection and the test times
out.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit 8942f0d)
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.

1 participant