-
v2026.06.07
Stablereleased this
2026-06-07 19:15:01 -04:00 | 81 commits to main since this releaseSingle-fix release on the per-day mutable CalVer scheme. (PR #88.)
Sonos — a single transport SOAP failure no longer reverts to local (Android)
The motivating bug: playing to a Sonos speaker, the phone locked, and a single transport command (lock-screen / Bluetooth / watch media button, or a queue-resync
play) issued during a WiFi power-save stall flashed "Disconnected from <Sonos>" and dropped playback back to the phone — even though the speaker was perfectly reachable.A transport command issued during screen-off WiFi sleep / Doze hit the 2 s connect timeout and threw.
handleSoapFailurethen cancelled the poll loop and firedonDropon that single failure, bypassing the poll loop's deliberate 30-consecutive-failure tolerance (DROP_THRESHOLD, bumped from 3 precisely for this case).Fix — make the 1 Hz poll loop the sole drop arbiter:
- Transport SOAP commands now retry transient IO failures (
retryTransientIo: 3 attempts, 400 ms backoff) so a brief WiFi stall lands the command once WiFi wakes instead of abandoning it. ASoapFaultException(renderer answered and rejected the action) is not retried — the device is alive. handleTransportFailureno longer cancels the poll loop or firesonDrop; it logs and nudges an immediate poll so the UI reconciles to Sonos's actual state. If the renderer is truly gone, the poll loop trips the drop on its own viaDROP_THRESHOLD.retryTransientIoextracted as an internal top-level fn with a unit test (first-success, retry-then-succeed, exhaust-and-rethrow, no-retry-on-SoapFault).
Verify on device
- Play to a Sonos speaker, lock the phone, let WiFi sleep, then hit a lock-screen / Bluetooth / watch transport button → the command lands (once WiFi wakes); the app stays routed to Sonos instead of flashing "Disconnected" and reverting to local.
- Power off the Sonos mid-session → after ~30 s of failed polls the app drops to local on its own (the deliberate tolerance still fires).
Downloads
- Transport SOAP commands now retry transient IO failures (