From 7f640252a1a199b14ca006e77fe7b41ff9a789c4 Mon Sep 17 00:00:00 2001 From: Andrew Sayre <6730289+andrewsayre@users.noreply.github.com> Date: Sat, 22 Mar 2025 14:12:51 -0500 Subject: [PATCH] Use Debouncer helper in HEOS Coordinator (#141133) Use Debouncer --- homeassistant/components/heos/coordinator.py | 41 ++++++-------------- 1 file changed, 12 insertions(+), 29 deletions(-) diff --git a/homeassistant/components/heos/coordinator.py b/homeassistant/components/heos/coordinator.py index 0bc948bccd7..5e72eb1427e 100644 --- a/homeassistant/components/heos/coordinator.py +++ b/homeassistant/components/heos/coordinator.py @@ -6,7 +6,6 @@ entities to update. Entities subscribe to entity-specific updates within the ent """ from collections.abc import Callable, Sequence -from datetime import datetime, timedelta import logging from typing import Any @@ -25,10 +24,10 @@ from pyheos import ( from homeassistant.config_entries import ConfigEntry from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_USERNAME, Platform -from homeassistant.core import CALLBACK_TYPE, HassJob, HomeAssistant, callback +from homeassistant.core import CALLBACK_TYPE, HomeAssistant, callback from homeassistant.exceptions import ConfigEntryNotReady from homeassistant.helpers import device_registry as dr, entity_registry as er -from homeassistant.helpers.event import async_call_later +from homeassistant.helpers.debounce import Debouncer from homeassistant.helpers.update_coordinator import DataUpdateCoordinator from .const import DOMAIN @@ -60,7 +59,13 @@ class HeosCoordinator(DataUpdateCoordinator[None]): ) ) self._platform_callbacks: list[Callable[[Sequence[HeosPlayer]], None]] = [] - self._update_sources_pending: bool = False + self._update_sources_debouncer = Debouncer( + hass, + _LOGGER, + immediate=True, + cooldown=2.0, + function=self._async_update_sources, + ) self._source_list: list[str] = [] self._favorites: dict[int, MediaItem] = {} self._inputs: Sequence[MediaItem] = [] @@ -182,31 +187,9 @@ class HeosCoordinator(DataUpdateCoordinator[None]): if event == const.EVENT_PLAYERS_CHANGED: assert data is not None self._async_handle_player_update_result(data) - elif ( - event in (const.EVENT_SOURCES_CHANGED, const.EVENT_USER_CHANGED) - and not self._update_sources_pending - ): - # Update the sources after a brief delay as we may have received multiple qualifying - # events at once and devices cannot handle immediately attempting to refresh sources. - self._update_sources_pending = True - - async def update_sources_job(_: datetime | None = None) -> None: - await self._async_update_sources() - self._update_sources_pending = False - self.async_update_listeners() - - assert self.config_entry is not None - self.config_entry.async_on_unload( - async_call_later( - self.hass, - timedelta(seconds=1), - HassJob( - update_sources_job, - "heos_update_sources", - cancel_on_shutdown=True, - ), - ) - ) + elif event in (const.EVENT_SOURCES_CHANGED, const.EVENT_USER_CHANGED): + # Debounce because we may have received multiple qualifying events in rapid succession. + await self._update_sources_debouncer.async_call() self.async_update_listeners() def _async_update_player_ids(self, updated_player_ids: dict[int, int]) -> None: