Add async_track_state_reported_event to fix integration performance regression (#120622)
split from https://github.com/home-assistant/core/pull/120621pull/120621/head^2
parent
f189d87fe9
commit
a5a631148e
|
@ -17,6 +17,7 @@ from typing import TYPE_CHECKING, Any, Concatenate, Generic, TypeVar
|
|||
from homeassistant.const import (
|
||||
EVENT_CORE_CONFIG_UPDATE,
|
||||
EVENT_STATE_CHANGED,
|
||||
EVENT_STATE_REPORTED,
|
||||
MATCH_ALL,
|
||||
SUN_EVENT_SUNRISE,
|
||||
SUN_EVENT_SUNSET,
|
||||
|
@ -26,6 +27,7 @@ from homeassistant.core import (
|
|||
Event,
|
||||
# Explicit reexport of 'EventStateChangedData' for backwards compatibility
|
||||
EventStateChangedData as EventStateChangedData, # noqa: PLC0414
|
||||
EventStateReportedData,
|
||||
HassJob,
|
||||
HassJobType,
|
||||
HomeAssistant,
|
||||
|
@ -57,6 +59,9 @@ from .typing import TemplateVarsType
|
|||
_TRACK_STATE_CHANGE_DATA: HassKey[_KeyedEventData[EventStateChangedData]] = HassKey(
|
||||
"track_state_change_data"
|
||||
)
|
||||
_TRACK_STATE_REPORTED_DATA: HassKey[_KeyedEventData[EventStateReportedData]] = HassKey(
|
||||
"track_state_reported_data"
|
||||
)
|
||||
_TRACK_STATE_ADDED_DOMAIN_DATA: HassKey[_KeyedEventData[EventStateChangedData]] = (
|
||||
HassKey("track_state_added_domain_data")
|
||||
)
|
||||
|
@ -324,8 +329,8 @@ def async_track_state_change_event(
|
|||
@callback
|
||||
def _async_dispatch_entity_id_event(
|
||||
hass: HomeAssistant,
|
||||
callbacks: dict[str, list[HassJob[[Event[EventStateChangedData]], Any]]],
|
||||
event: Event[EventStateChangedData],
|
||||
callbacks: dict[str, list[HassJob[[Event[_TypedDictT]], Any]]],
|
||||
event: Event[_TypedDictT],
|
||||
) -> None:
|
||||
"""Dispatch to listeners."""
|
||||
if not (callbacks_list := callbacks.get(event.data["entity_id"])):
|
||||
|
@ -342,10 +347,10 @@ def _async_dispatch_entity_id_event(
|
|||
|
||||
|
||||
@callback
|
||||
def _async_state_change_filter(
|
||||
def _async_state_filter(
|
||||
hass: HomeAssistant,
|
||||
callbacks: dict[str, list[HassJob[[Event[EventStateChangedData]], Any]]],
|
||||
event_data: EventStateChangedData,
|
||||
callbacks: dict[str, list[HassJob[[Event[_TypedDictT]], Any]]],
|
||||
event_data: _TypedDictT,
|
||||
) -> bool:
|
||||
"""Filter state changes by entity_id."""
|
||||
return event_data["entity_id"] in callbacks
|
||||
|
@ -355,7 +360,7 @@ _KEYED_TRACK_STATE_CHANGE = _KeyedEventTracker(
|
|||
key=_TRACK_STATE_CHANGE_DATA,
|
||||
event_type=EVENT_STATE_CHANGED,
|
||||
dispatcher_callable=_async_dispatch_entity_id_event,
|
||||
filter_callable=_async_state_change_filter,
|
||||
filter_callable=_async_state_filter,
|
||||
)
|
||||
|
||||
|
||||
|
@ -372,6 +377,26 @@ def _async_track_state_change_event(
|
|||
)
|
||||
|
||||
|
||||
_KEYED_TRACK_STATE_REPORTED = _KeyedEventTracker(
|
||||
key=_TRACK_STATE_REPORTED_DATA,
|
||||
event_type=EVENT_STATE_REPORTED,
|
||||
dispatcher_callable=_async_dispatch_entity_id_event,
|
||||
filter_callable=_async_state_filter,
|
||||
)
|
||||
|
||||
|
||||
def async_track_state_reported_event(
|
||||
hass: HomeAssistant,
|
||||
entity_ids: str | Iterable[str],
|
||||
action: Callable[[Event[EventStateReportedData]], Any],
|
||||
job_type: HassJobType | None = None,
|
||||
) -> CALLBACK_TYPE:
|
||||
"""Track EVENT_STATE_REPORTED by entity_id without lowercasing."""
|
||||
return _async_track_event(
|
||||
_KEYED_TRACK_STATE_REPORTED, hass, entity_ids, action, job_type
|
||||
)
|
||||
|
||||
|
||||
@callback
|
||||
def _remove_empty_listener() -> None:
|
||||
"""Remove a listener that does nothing."""
|
||||
|
|
|
@ -15,7 +15,13 @@ import pytest
|
|||
|
||||
from homeassistant.const import MATCH_ALL
|
||||
import homeassistant.core as ha
|
||||
from homeassistant.core import Event, EventStateChangedData, HomeAssistant, callback
|
||||
from homeassistant.core import (
|
||||
Event,
|
||||
EventStateChangedData,
|
||||
EventStateReportedData,
|
||||
HomeAssistant,
|
||||
callback,
|
||||
)
|
||||
from homeassistant.exceptions import TemplateError
|
||||
from homeassistant.helpers.device_registry import EVENT_DEVICE_REGISTRY_UPDATED
|
||||
from homeassistant.helpers.entity_registry import EVENT_ENTITY_REGISTRY_UPDATED
|
||||
|
@ -34,6 +40,7 @@ from homeassistant.helpers.event import (
|
|||
async_track_state_change_event,
|
||||
async_track_state_change_filtered,
|
||||
async_track_state_removed_domain,
|
||||
async_track_state_reported_event,
|
||||
async_track_sunrise,
|
||||
async_track_sunset,
|
||||
async_track_template,
|
||||
|
@ -4907,3 +4914,26 @@ async def test_track_point_in_time_repr(
|
|||
assert "Exception in callback _TrackPointUTCTime" in caplog.text
|
||||
assert "._raise_exception" in caplog.text
|
||||
await hass.async_block_till_done(wait_background_tasks=True)
|
||||
|
||||
|
||||
async def test_async_track_state_reported_event(hass: HomeAssistant) -> None:
|
||||
"""Test async_track_state_reported_event."""
|
||||
tracker_called: list[ha.State] = []
|
||||
|
||||
@ha.callback
|
||||
def single_run_callback(event: Event[EventStateReportedData]) -> None:
|
||||
new_state = event.data["new_state"]
|
||||
tracker_called.append(new_state)
|
||||
|
||||
unsub = async_track_state_reported_event(
|
||||
hass, ["light.bowl", "light.top"], single_run_callback
|
||||
)
|
||||
hass.states.async_set("light.bowl", "on")
|
||||
hass.states.async_set("light.top", "on")
|
||||
await hass.async_block_till_done()
|
||||
assert len(tracker_called) == 0
|
||||
hass.states.async_set("light.bowl", "on")
|
||||
hass.states.async_set("light.top", "on")
|
||||
await hass.async_block_till_done()
|
||||
assert len(tracker_called) == 2
|
||||
unsub()
|
||||
|
|
Loading…
Reference in New Issue