client: fix race that drops a group's subscription callbacks, making … - #145
client: fix race that drops a group's subscription callbacks, making …#145vanackere wants to merge 1 commit into
Conversation
…the speaker appear unresponsive `_handle_groups_event` is synchronous, but `_setup_group` is scheduled as an async task. When two group events for the same id arrive back-to-back — in practice this happens whenever the Sonos household publishes a quick burst of topology updates (a player joining or leaving a group, a speaker coming back online after a network blip, a controller reload triggering an immediate refresh) — the second event observes `group_id not in self._groups` (the first task has not run yet), and a second `_setup_group` task is queued. Both tasks then call `.subscribe()` for the same event id, and the second one silently overwrites the first listener in `_listeners`. The original listener never fires again, so events for that group stop being processed — to the user, the speaker stops reflecting playback state and looks frozen or disappears from the controller. Fix: insert the `SonosGroup` into `self._groups` synchronously before scheduling `_setup_group`, so a racing event sees the group as known and takes the `update_data` path instead of queuing a duplicate setup.
|
Adding some context: in my household one of the players (a Sonos Roam) was offline. After restarting the Music Assistant Sonos integration, two of the active speakers (Living Room, Office) consistently failed to register with the provider — they would only appear as their AirPlay siblings, never as Sonos players. The log carried a single I'm not certain why an offline player in |
…the speaker appear unresponsive
_handle_groups_eventis synchronous, but_setup_groupis scheduled as an async task. When two group events for the same id arrive back-to-back — in practice this happens whenever the Sonos household publishes a quick burst of topology updates (a player joining or leaving a group, a speaker coming back online after a network blip, a controller reload triggering an immediate refresh) — the second event observesgroup_id not in self._groups(the first task has not run yet), and a second_setup_grouptask is queued. Both tasks then call.subscribe()for the same event id, and the second one silently overwrites the first listener in_listeners. The original listener never fires again, so events for that group stop being processed — to the user, the speaker stops reflecting playback state and looks frozen or disappears from the controller.Fix: insert the
SonosGroupintoself._groupssynchronously before scheduling_setup_group, so a racing event sees the group as known and takes theupdate_datapath instead of queuing a duplicate setup.