mirror of
https://github.com/home-assistant/core.git
synced 2025-07-25 14:17:45 +00:00
Avoid core/supervisor stats API calls when no entities need them (#102362)
This commit is contained in:
parent
af0b53cc79
commit
82c0610050
@ -57,9 +57,6 @@ from .addon_manager import AddonError, AddonInfo, AddonManager, AddonState # no
|
|||||||
from .addon_panel import async_setup_addon_panel
|
from .addon_panel import async_setup_addon_panel
|
||||||
from .auth import async_setup_auth_view
|
from .auth import async_setup_auth_view
|
||||||
from .const import (
|
from .const import (
|
||||||
ADDON_UPDATE_CHANGELOG,
|
|
||||||
ADDON_UPDATE_INFO,
|
|
||||||
ADDON_UPDATE_STATS,
|
|
||||||
ATTR_ADDON,
|
ATTR_ADDON,
|
||||||
ATTR_ADDONS,
|
ATTR_ADDONS,
|
||||||
ATTR_AUTO_UPDATE,
|
ATTR_AUTO_UPDATE,
|
||||||
@ -76,6 +73,10 @@ from .const import (
|
|||||||
ATTR_STATE,
|
ATTR_STATE,
|
||||||
ATTR_URL,
|
ATTR_URL,
|
||||||
ATTR_VERSION,
|
ATTR_VERSION,
|
||||||
|
CONTAINER_CHANGELOG,
|
||||||
|
CONTAINER_INFO,
|
||||||
|
CONTAINER_STATS,
|
||||||
|
CORE_CONTAINER,
|
||||||
DATA_KEY_ADDONS,
|
DATA_KEY_ADDONS,
|
||||||
DATA_KEY_CORE,
|
DATA_KEY_CORE,
|
||||||
DATA_KEY_HOST,
|
DATA_KEY_HOST,
|
||||||
@ -83,6 +84,7 @@ from .const import (
|
|||||||
DATA_KEY_SUPERVISOR,
|
DATA_KEY_SUPERVISOR,
|
||||||
DATA_KEY_SUPERVISOR_ISSUES,
|
DATA_KEY_SUPERVISOR_ISSUES,
|
||||||
DOMAIN,
|
DOMAIN,
|
||||||
|
SUPERVISOR_CONTAINER,
|
||||||
SupervisorEntityModel,
|
SupervisorEntityModel,
|
||||||
)
|
)
|
||||||
from .discovery import HassioServiceInfo, async_setup_discovery_view # noqa: F401
|
from .discovery import HassioServiceInfo, async_setup_discovery_view # noqa: F401
|
||||||
@ -805,9 +807,9 @@ class HassioDataUpdateCoordinator(DataUpdateCoordinator):
|
|||||||
self.entry_id = config_entry.entry_id
|
self.entry_id = config_entry.entry_id
|
||||||
self.dev_reg = dev_reg
|
self.dev_reg = dev_reg
|
||||||
self.is_hass_os = (get_info(self.hass) or {}).get("hassos") is not None
|
self.is_hass_os = (get_info(self.hass) or {}).get("hassos") is not None
|
||||||
self._enabled_updates_by_addon: defaultdict[
|
self._container_updates: defaultdict[str, dict[str, set[str]]] = defaultdict(
|
||||||
str, dict[str, set[str]]
|
lambda: defaultdict(set)
|
||||||
] = defaultdict(lambda: defaultdict(set))
|
)
|
||||||
|
|
||||||
async def _async_update_data(self) -> dict[str, Any]:
|
async def _async_update_data(self) -> dict[str, Any]:
|
||||||
"""Update data via library."""
|
"""Update data via library."""
|
||||||
@ -910,23 +912,24 @@ class HassioDataUpdateCoordinator(DataUpdateCoordinator):
|
|||||||
|
|
||||||
async def force_data_refresh(self, first_update: bool) -> None:
|
async def force_data_refresh(self, first_update: bool) -> None:
|
||||||
"""Force update of the addon info."""
|
"""Force update of the addon info."""
|
||||||
|
container_updates = self._container_updates
|
||||||
|
|
||||||
data = self.hass.data
|
data = self.hass.data
|
||||||
hassio = self.hassio
|
hassio = self.hassio
|
||||||
(
|
updates = {
|
||||||
data[DATA_INFO],
|
DATA_INFO: hassio.get_info(),
|
||||||
data[DATA_CORE_INFO],
|
DATA_CORE_INFO: hassio.get_core_info(),
|
||||||
data[DATA_CORE_STATS],
|
DATA_SUPERVISOR_INFO: hassio.get_supervisor_info(),
|
||||||
data[DATA_SUPERVISOR_INFO],
|
DATA_OS_INFO: hassio.get_os_info(),
|
||||||
data[DATA_SUPERVISOR_STATS],
|
}
|
||||||
data[DATA_OS_INFO],
|
if first_update or CONTAINER_STATS in container_updates[CORE_CONTAINER]:
|
||||||
) = await asyncio.gather(
|
updates[DATA_CORE_STATS] = hassio.get_core_stats()
|
||||||
hassio.get_info(),
|
if first_update or CONTAINER_STATS in container_updates[SUPERVISOR_CONTAINER]:
|
||||||
hassio.get_core_info(),
|
updates[DATA_SUPERVISOR_STATS] = hassio.get_supervisor_stats()
|
||||||
hassio.get_core_stats(),
|
|
||||||
hassio.get_supervisor_info(),
|
results = await asyncio.gather(*updates.values())
|
||||||
hassio.get_supervisor_stats(),
|
for key, result in zip(updates, results):
|
||||||
hassio.get_os_info(),
|
data[key] = result
|
||||||
)
|
|
||||||
|
|
||||||
_addon_data = data[DATA_SUPERVISOR_INFO].get("addons", [])
|
_addon_data = data[DATA_SUPERVISOR_INFO].get("addons", [])
|
||||||
all_addons: list[str] = []
|
all_addons: list[str] = []
|
||||||
@ -940,37 +943,36 @@ class HassioDataUpdateCoordinator(DataUpdateCoordinator):
|
|||||||
# Update add-on info if its the first update or
|
# Update add-on info if its the first update or
|
||||||
# there is at least one entity that needs the data.
|
# there is at least one entity that needs the data.
|
||||||
#
|
#
|
||||||
# When entities are added they call async_enable_addon_updates
|
# When entities are added they call async_enable_container_updates
|
||||||
# to enable updates for the endpoints they need via
|
# to enable updates for the endpoints they need via
|
||||||
# async_added_to_hass. This ensures that we only update
|
# async_added_to_hass. This ensures that we only update
|
||||||
# the data for the endpoints that are needed to avoid unnecessary
|
# the data for the endpoints that are needed to avoid unnecessary
|
||||||
# API calls since otherwise we would fetch stats for all add-ons
|
# API calls since otherwise we would fetch stats for all containers
|
||||||
# and throw them away.
|
# and throw them away.
|
||||||
#
|
#
|
||||||
enabled_updates_by_addon = self._enabled_updates_by_addon
|
|
||||||
for data_key, update_func, enabled_key, wanted_addons in (
|
for data_key, update_func, enabled_key, wanted_addons in (
|
||||||
(
|
(
|
||||||
DATA_ADDONS_STATS,
|
DATA_ADDONS_STATS,
|
||||||
self._update_addon_stats,
|
self._update_addon_stats,
|
||||||
ADDON_UPDATE_STATS,
|
CONTAINER_STATS,
|
||||||
started_addons,
|
started_addons,
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
DATA_ADDONS_CHANGELOGS,
|
DATA_ADDONS_CHANGELOGS,
|
||||||
self._update_addon_changelog,
|
self._update_addon_changelog,
|
||||||
ADDON_UPDATE_CHANGELOG,
|
CONTAINER_CHANGELOG,
|
||||||
all_addons,
|
all_addons,
|
||||||
),
|
),
|
||||||
(DATA_ADDONS_INFO, self._update_addon_info, ADDON_UPDATE_INFO, all_addons),
|
(DATA_ADDONS_INFO, self._update_addon_info, CONTAINER_INFO, all_addons),
|
||||||
):
|
):
|
||||||
data.setdefault(data_key, {}).update(
|
container_data: dict[str, Any] = data.setdefault(data_key, {})
|
||||||
|
container_data.update(
|
||||||
dict(
|
dict(
|
||||||
await asyncio.gather(
|
await asyncio.gather(
|
||||||
*[
|
*[
|
||||||
update_func(slug)
|
update_func(slug)
|
||||||
for slug in wanted_addons
|
for slug in wanted_addons
|
||||||
if first_update
|
if first_update or enabled_key in container_updates[slug]
|
||||||
or enabled_key in enabled_updates_by_addon[slug]
|
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@ -1004,11 +1006,11 @@ class HassioDataUpdateCoordinator(DataUpdateCoordinator):
|
|||||||
return (slug, None)
|
return (slug, None)
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def async_enable_addon_updates(
|
def async_enable_container_updates(
|
||||||
self, slug: str, entity_id: str, types: set[str]
|
self, slug: str, entity_id: str, types: set[str]
|
||||||
) -> CALLBACK_TYPE:
|
) -> CALLBACK_TYPE:
|
||||||
"""Enable updates for an add-on."""
|
"""Enable updates for an add-on."""
|
||||||
enabled_updates = self._enabled_updates_by_addon[slug]
|
enabled_updates = self._container_updates[slug]
|
||||||
for key in types:
|
for key in types:
|
||||||
enabled_updates[key].add(entity_id)
|
enabled_updates[key].add(entity_id)
|
||||||
|
|
||||||
|
@ -82,19 +82,22 @@ PLACEHOLDER_KEY_COMPONENTS = "components"
|
|||||||
|
|
||||||
ISSUE_KEY_SYSTEM_DOCKER_CONFIG = "issue_system_docker_config"
|
ISSUE_KEY_SYSTEM_DOCKER_CONFIG = "issue_system_docker_config"
|
||||||
|
|
||||||
ADDON_UPDATE_STATS = "stats"
|
CORE_CONTAINER = "homeassistant"
|
||||||
ADDON_UPDATE_CHANGELOG = "changelog"
|
SUPERVISOR_CONTAINER = "hassio_supervisor"
|
||||||
ADDON_UPDATE_INFO = "info"
|
|
||||||
|
CONTAINER_STATS = "stats"
|
||||||
|
CONTAINER_CHANGELOG = "changelog"
|
||||||
|
CONTAINER_INFO = "info"
|
||||||
|
|
||||||
# This is a mapping of which endpoint the key in the addon data
|
# This is a mapping of which endpoint the key in the addon data
|
||||||
# is obtained from so we know which endpoint to update when the
|
# is obtained from so we know which endpoint to update when the
|
||||||
# coordinator polls for updates.
|
# coordinator polls for updates.
|
||||||
KEY_TO_UPDATE_TYPES: dict[str, set[str]] = {
|
KEY_TO_UPDATE_TYPES: dict[str, set[str]] = {
|
||||||
ATTR_VERSION_LATEST: {ADDON_UPDATE_INFO, ADDON_UPDATE_CHANGELOG},
|
ATTR_VERSION_LATEST: {CONTAINER_INFO, CONTAINER_CHANGELOG},
|
||||||
ATTR_MEMORY_PERCENT: {ADDON_UPDATE_STATS},
|
ATTR_MEMORY_PERCENT: {CONTAINER_STATS},
|
||||||
ATTR_CPU_PERCENT: {ADDON_UPDATE_STATS},
|
ATTR_CPU_PERCENT: {CONTAINER_STATS},
|
||||||
ATTR_VERSION: {ADDON_UPDATE_INFO},
|
ATTR_VERSION: {CONTAINER_INFO},
|
||||||
ATTR_STATE: {ADDON_UPDATE_INFO},
|
ATTR_STATE: {CONTAINER_INFO},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -10,12 +10,14 @@ from homeassistant.helpers.update_coordinator import CoordinatorEntity
|
|||||||
from . import DOMAIN, HassioDataUpdateCoordinator
|
from . import DOMAIN, HassioDataUpdateCoordinator
|
||||||
from .const import (
|
from .const import (
|
||||||
ATTR_SLUG,
|
ATTR_SLUG,
|
||||||
|
CORE_CONTAINER,
|
||||||
DATA_KEY_ADDONS,
|
DATA_KEY_ADDONS,
|
||||||
DATA_KEY_CORE,
|
DATA_KEY_CORE,
|
||||||
DATA_KEY_HOST,
|
DATA_KEY_HOST,
|
||||||
DATA_KEY_OS,
|
DATA_KEY_OS,
|
||||||
DATA_KEY_SUPERVISOR,
|
DATA_KEY_SUPERVISOR,
|
||||||
KEY_TO_UPDATE_TYPES,
|
KEY_TO_UPDATE_TYPES,
|
||||||
|
SUPERVISOR_CONTAINER,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -52,7 +54,7 @@ class HassioAddonEntity(CoordinatorEntity[HassioDataUpdateCoordinator]):
|
|||||||
await super().async_added_to_hass()
|
await super().async_added_to_hass()
|
||||||
update_types = KEY_TO_UPDATE_TYPES[self.entity_description.key]
|
update_types = KEY_TO_UPDATE_TYPES[self.entity_description.key]
|
||||||
self.async_on_remove(
|
self.async_on_remove(
|
||||||
self.coordinator.async_enable_addon_updates(
|
self.coordinator.async_enable_container_updates(
|
||||||
self._addon_slug, self.entity_id, update_types
|
self._addon_slug, self.entity_id, update_types
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@ -136,6 +138,16 @@ class HassioSupervisorEntity(CoordinatorEntity[HassioDataUpdateCoordinator]):
|
|||||||
in self.coordinator.data[DATA_KEY_SUPERVISOR]
|
in self.coordinator.data[DATA_KEY_SUPERVISOR]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
async def async_added_to_hass(self) -> None:
|
||||||
|
"""Subscribe to updates."""
|
||||||
|
await super().async_added_to_hass()
|
||||||
|
update_types = KEY_TO_UPDATE_TYPES[self.entity_description.key]
|
||||||
|
self.async_on_remove(
|
||||||
|
self.coordinator.async_enable_container_updates(
|
||||||
|
SUPERVISOR_CONTAINER, self.entity_id, update_types
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class HassioCoreEntity(CoordinatorEntity[HassioDataUpdateCoordinator]):
|
class HassioCoreEntity(CoordinatorEntity[HassioDataUpdateCoordinator]):
|
||||||
"""Base Entity for Core."""
|
"""Base Entity for Core."""
|
||||||
@ -161,3 +173,13 @@ class HassioCoreEntity(CoordinatorEntity[HassioDataUpdateCoordinator]):
|
|||||||
and DATA_KEY_CORE in self.coordinator.data
|
and DATA_KEY_CORE in self.coordinator.data
|
||||||
and self.entity_description.key in self.coordinator.data[DATA_KEY_CORE]
|
and self.entity_description.key in self.coordinator.data[DATA_KEY_CORE]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
async def async_added_to_hass(self) -> None:
|
||||||
|
"""Subscribe to updates."""
|
||||||
|
await super().async_added_to_hass()
|
||||||
|
update_types = KEY_TO_UPDATE_TYPES[self.entity_description.key]
|
||||||
|
self.async_on_remove(
|
||||||
|
self.coordinator.async_enable_container_updates(
|
||||||
|
CORE_CONTAINER, self.entity_id, update_types
|
||||||
|
)
|
||||||
|
)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user