Fix sonos overloading the executor when there are many devices (#112482)

This commit is contained in:
J. Nick Koston 2024-03-06 08:55:47 -10:00 committed by GitHub
parent 7096701cab
commit 0f3838e7a8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -8,7 +8,7 @@ import datetime
from functools import partial
import logging
import time
from typing import Any, cast
from typing import TYPE_CHECKING, Any, cast
import defusedxml.ElementTree as ET
from soco.core import SoCo
@ -64,6 +64,9 @@ from .helpers import soco_error
from .media import SonosMedia
from .statistics import ActivityStatistics, EventStatistics
if TYPE_CHECKING:
from . import SonosData
NEVER_TIME = -1200.0
RESUB_COOLDOWN_SECONDS = 10.0
EVENT_CHARGING = {
@ -97,6 +100,7 @@ class SonosSpeaker:
) -> None:
"""Initialize a SonosSpeaker."""
self.hass = hass
self.data: SonosData = hass.data[DATA_SONOS]
self.soco = soco
self.websocket: SonosWebsocket | None = None
self.household_id: str = soco.household_id
@ -183,7 +187,7 @@ class SonosSpeaker:
)
dispatch_pairs: tuple[tuple[str, Callable[..., Any]], ...] = (
(SONOS_CHECK_ACTIVITY, self.async_check_activity),
(SONOS_SPEAKER_ADDED, self.update_group_for_uid),
(SONOS_SPEAKER_ADDED, self.async_update_group_for_uid),
(f"{SONOS_REBOOTED}-{self.soco.uid}", self.async_rebooted),
(f"{SONOS_SPEAKER_ACTIVITY}-{self.soco.uid}", self.speaker_activity),
(f"{SONOS_VANISHED}-{self.soco.uid}", self.async_vanished),
@ -272,12 +276,12 @@ class SonosSpeaker:
@property
def alarms(self) -> SonosAlarms:
"""Return the SonosAlarms instance for this household."""
return self.hass.data[DATA_SONOS].alarms[self.household_id]
return self.data.alarms[self.household_id]
@property
def favorites(self) -> SonosFavorites:
"""Return the SonosFavorites instance for this household."""
return self.hass.data[DATA_SONOS].favorites[self.household_id]
return self.data.favorites[self.household_id]
@property
def is_coordinator(self) -> bool:
@ -496,9 +500,7 @@ class SonosSpeaker:
"x-rincon:"
):
new_coordinator_uid = av_transport_uri.split(":")[-1]
if new_coordinator_speaker := self.hass.data[DATA_SONOS].discovered.get(
new_coordinator_uid
):
if new_coordinator_speaker := self.data.discovered.get(new_coordinator_uid):
_LOGGER.debug(
"Media update coordinator (%s) received for %s",
new_coordinator_speaker.zone_name,
@ -657,7 +659,7 @@ class SonosSpeaker:
await self.async_unsubscribe()
self.hass.data[DATA_SONOS].discovery_known.discard(self.soco.uid)
self.data.discovery_known.discard(self.soco.uid)
async def async_vanished(self, reason: str) -> None:
"""Handle removal of speaker when marked as vanished."""
@ -784,15 +786,16 @@ class SonosSpeaker:
"""Update group topology when polling."""
self.hass.add_job(self.create_update_groups_coro())
def update_group_for_uid(self, uid: str) -> None:
@callback
def async_update_group_for_uid(self, uid: str) -> None:
"""Update group topology if uid is missing."""
if uid not in self._group_members_missing:
return
missing_zone = self.hass.data[DATA_SONOS].discovered[uid].zone_name
missing_zone = self.data.discovered[uid].zone_name
_LOGGER.debug(
"%s was missing, adding to %s group", missing_zone, self.zone_name
)
self.update_groups()
self.hass.async_create_task(self.create_update_groups_coro(), eager_start=True)
@callback
def async_update_groups(self, event: SonosEvent) -> None:
@ -866,7 +869,7 @@ class SonosSpeaker:
sonos_group_entities = []
for uid in group:
speaker = self.hass.data[DATA_SONOS].discovered.get(uid)
speaker = self.data.discovered.get(uid)
if speaker:
self._group_members_missing.discard(uid)
sonos_group.append(speaker)
@ -894,10 +897,7 @@ class SonosSpeaker:
self.async_write_entity_states()
for joined_uid in group[1:]:
joined_speaker: SonosSpeaker = self.hass.data[
DATA_SONOS
].discovered.get(joined_uid)
if joined_speaker:
if joined_speaker := self.data.discovered.get(joined_uid):
joined_speaker.coordinator = self
joined_speaker.sonos_group = sonos_group
joined_speaker.sonos_group_entities = sonos_group_entities
@ -908,13 +908,13 @@ class SonosSpeaker:
async def _async_handle_group_event(event: SonosEvent | None) -> None:
"""Get async lock and handle event."""
async with self.hass.data[DATA_SONOS].topology_condition:
async with self.data.topology_condition:
group = await _async_extract_group(event)
if self.soco.uid == group[0]:
_async_regroup(group)
self.hass.data[DATA_SONOS].topology_condition.notify_all()
self.data.topology_condition.notify_all()
return _async_handle_group_event(event)