WIP: fix(connect): re-resolve context after dealer disconnect (silent resume)#1713
WIP: fix(connect): re-resolve context after dealer disconnect (silent resume)#1713tobsch wants to merge 1 commit into
Conversation
Corrected root-cause analysis (my initial patch is insufficient)After testing the The context is wiped in
So the burst defeats a A correct fix needs a recovery context uri that survives the wipe, e.g. stash the uri in |
When the device becomes inactive (e.g. Spotify drops the idle dealer
during a pause and a ClusterUpdate marks another device active),
`became_inactive` -> `reset_context(ResetContext::Completely)` wipes both
`self.context` and `player.context_uri`. On resume the device
re-activates but `set_active_context` -> `get_context` returns
`NoContext` ("context is not available") and playback never starts —
the device shows active in the app but stays silent until the connect
host is restarted.
Preserve the last non-empty context uri across the reset in a new
`ConnectState::recovery_context_uri` field, and on re-activation, if no
context is loaded, re-resolve it (`ResolveContext::from_uri`,
`ContextAction::Replace`). The value is taken (cleared) on use so we
don't repeatedly retry the same context.
Doing the recovery at activation (rather than at disconnect) avoids the
burst-of-disconnects race where each `handle_disconnect` clears the
resolver: re-activation happens once, after the dealer has settled.
WIP: reproduced on a multi-zone setup where pause→(idle dealer drop)→
resume reliably produced the silent-resume + `context is not available`
spam; with this patch resume re-resolves and plays. Feedback welcome on
whether `handle_activate` is the right seam vs. the transfer/load paths.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
3a57d20 to
1430e2a
Compare
|
Retested this branch (commit Result: does not fix the symptom. On resume I still get the burst of: and playback plays the small buffered bit then stops (device shows active in the app, silent). Likely why: the recovery hinges on stashing So |
|
Closing this — after testing on real hardware it does not fix the symptom. The approach (stash The real failure is in |
Problem
On a Spotify Connect device, pause → (idle) → resume can leave the device active in the Spotify app but silent. The log shows:
repeated, with no audio. Playback only recovers after the connect host is restarted.
Root cause
Spirc::handle_disconnect()callsself.context_resolver.clear(). The dealer connection gets dropped while paused — Spotify routinely drops idle Connect dealer connections, and this is much more frequent on accounts running several simultaneous Connect devices (multi-room). That triggershandle_disconnect, wiping the resolver queue.On resume,
set_active_context(ContextType::Default)callsget_context(), which returnsStateError::NoContextbecause the context data is gone and nothing re-fetches it. The resume silently fails.The transfer path (
handle_transfer) has a partial fallback ("continuing transfer in an unknown state"), but a plain resume on the existing context does not re-resolve.Change
Capture the current
context_uribefore clearing the resolver, then re-enqueue it as aResolveContext::from_uri(.., ContextAction::Replace)so the context is re-resolved on the next activation.Re-enqueuing is harmless for intentional disconnects: it only makes the context resolvable again; it does not start playback or re-acquire active status.
Open questions for reviewers
handle_disconnectthe right seam, or should the re-resolve happen on reconnect inhandle_connection_id_update(gated oncontext_urinon-empty &&get_context().is_err())? The reconnect side is more precise but has several early-return branches.Disconnectcommand / shutdown? Currently it fires for all; the wasted resolve on intentional disconnect is negligible but not zero.Testing
Reproduced on a multi-zone setup (several Connect devices on one account) where pausing for a minute then resuming reliably produced the silent-resume +
context is not availablespam. With the patch, resume re-resolves and plays. Have not added unit coverage yet — pointers welcome on where Connect state transitions are tested.🤖 Generated with Claude Code