mirror of
https://github.com/home-assistant/core.git
synced 2025-07-14 08:47:10 +00:00
Ensure all async_track_state_change_event callbacks run if one throws (#37179)
This commit is contained in:
parent
c1194c90cb
commit
a63a11a11a
@ -1,6 +1,7 @@
|
|||||||
"""Helpers for listening to events."""
|
"""Helpers for listening to events."""
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
import functools as ft
|
import functools as ft
|
||||||
|
import logging
|
||||||
from typing import Any, Awaitable, Callable, Dict, Iterable, Optional, Union
|
from typing import Any, Awaitable, Callable, Dict, Iterable, Optional, Union
|
||||||
|
|
||||||
import attr
|
import attr
|
||||||
@ -24,6 +25,8 @@ from homeassistant.util.async_ import run_callback_threadsafe
|
|||||||
TRACK_STATE_CHANGE_CALLBACKS = "track_state_change_callbacks"
|
TRACK_STATE_CHANGE_CALLBACKS = "track_state_change_callbacks"
|
||||||
TRACK_STATE_CHANGE_LISTENER = "track_state_change_listener"
|
TRACK_STATE_CHANGE_LISTENER = "track_state_change_listener"
|
||||||
|
|
||||||
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
# PyLint does not like the use of threaded_listener_factory
|
# PyLint does not like the use of threaded_listener_factory
|
||||||
# pylint: disable=invalid-name
|
# pylint: disable=invalid-name
|
||||||
|
|
||||||
@ -146,7 +149,12 @@ def async_track_state_change_event(
|
|||||||
return
|
return
|
||||||
|
|
||||||
for action in entity_callbacks[entity_id]:
|
for action in entity_callbacks[entity_id]:
|
||||||
hass.async_run_job(action, event)
|
try:
|
||||||
|
hass.async_run_job(action, event)
|
||||||
|
except Exception: # pylint: disable=broad-except
|
||||||
|
_LOGGER.exception(
|
||||||
|
"Error while processing state changed for %s", entity_id
|
||||||
|
)
|
||||||
|
|
||||||
hass.data[TRACK_STATE_CHANGE_LISTENER] = hass.bus.async_listen(
|
hass.data[TRACK_STATE_CHANGE_LISTENER] = hass.bus.async_listen(
|
||||||
EVENT_STATE_CHANGED, _async_state_change_dispatcher
|
EVENT_STATE_CHANGED, _async_state_change_dispatcher
|
||||||
|
@ -183,12 +183,19 @@ async def test_async_track_state_change_event(hass):
|
|||||||
|
|
||||||
multiple_entity_id_tracker.append((old_state, new_state))
|
multiple_entity_id_tracker.append((old_state, new_state))
|
||||||
|
|
||||||
|
@ha.callback
|
||||||
|
def callback_that_throws(event):
|
||||||
|
raise ValueError
|
||||||
|
|
||||||
unsub_single = async_track_state_change_event(
|
unsub_single = async_track_state_change_event(
|
||||||
hass, ["light.Bowl"], single_run_callback
|
hass, ["light.Bowl"], single_run_callback
|
||||||
)
|
)
|
||||||
unsub_multi = async_track_state_change_event(
|
unsub_multi = async_track_state_change_event(
|
||||||
hass, ["light.Bowl", "switch.kitchen"], multiple_run_callback
|
hass, ["light.Bowl", "switch.kitchen"], multiple_run_callback
|
||||||
)
|
)
|
||||||
|
unsub_throws = async_track_state_change_event(
|
||||||
|
hass, ["light.Bowl", "switch.kitchen"], callback_that_throws
|
||||||
|
)
|
||||||
|
|
||||||
# Adding state to state machine
|
# Adding state to state machine
|
||||||
hass.states.async_set("light.Bowl", "on")
|
hass.states.async_set("light.Bowl", "on")
|
||||||
@ -247,6 +254,7 @@ async def test_async_track_state_change_event(hass):
|
|||||||
assert len(multiple_entity_id_tracker) == 7
|
assert len(multiple_entity_id_tracker) == 7
|
||||||
|
|
||||||
unsub_multi()
|
unsub_multi()
|
||||||
|
unsub_throws()
|
||||||
|
|
||||||
|
|
||||||
async def test_track_template(hass):
|
async def test_track_template(hass):
|
||||||
@ -429,6 +437,7 @@ async def test_track_same_state_simple_trigger_check_funct(hass):
|
|||||||
# Adding state to state machine
|
# Adding state to state machine
|
||||||
hass.states.async_set("light.Bowl", "on")
|
hass.states.async_set("light.Bowl", "on")
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
await hass.async_block_till_done()
|
||||||
assert len(callback_runs) == 0
|
assert len(callback_runs) == 0
|
||||||
assert check_func[-1][2].state == "on"
|
assert check_func[-1][2].state == "on"
|
||||||
assert check_func[-1][0] == "light.bowl"
|
assert check_func[-1][0] == "light.bowl"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user