mirror of
https://github.com/home-assistant/core.git
synced 2025-07-18 18:57:06 +00:00
Switch dispatcher to use async_run_hass_job (#74514)
* Switch dispatcher to use async_run_hass_job - Since we already wrap all the callbacks in catch_log_exception we can use async_run_hass_job here - The overhead of wrapping the call in a call_soon, queuing it and running it later usually exceeds the overhead of running the job itself * fix size change during iteration * fix out of order send * fix missing mocking in unifi test * Fix Legrand Home+ Control updating entities before the coordinator update had finished * stray debug
This commit is contained in:
parent
323d4a0e1b
commit
1dd9e705f2
@ -86,8 +86,8 @@ async def websocket_supervisor_event(
|
|||||||
hass: HomeAssistant, connection: ActiveConnection, msg: dict
|
hass: HomeAssistant, connection: ActiveConnection, msg: dict
|
||||||
):
|
):
|
||||||
"""Publish events from the Supervisor."""
|
"""Publish events from the Supervisor."""
|
||||||
async_dispatcher_send(hass, EVENT_SUPERVISOR_EVENT, msg[ATTR_DATA])
|
|
||||||
connection.send_result(msg[WS_ID])
|
connection.send_result(msg[WS_ID])
|
||||||
|
async_dispatcher_send(hass, EVENT_SUPERVISOR_EVENT, msg[ATTR_DATA])
|
||||||
|
|
||||||
|
|
||||||
@websocket_api.websocket_command(
|
@websocket_api.websocket_command(
|
||||||
|
@ -9,7 +9,7 @@ import voluptuous as vol
|
|||||||
|
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.const import CONF_CLIENT_ID, CONF_CLIENT_SECRET, Platform
|
from homeassistant.const import CONF_CLIENT_ID, CONF_CLIENT_SECRET, Platform
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant, callback
|
||||||
from homeassistant.helpers import (
|
from homeassistant.helpers import (
|
||||||
config_entry_oauth2_flow,
|
config_entry_oauth2_flow,
|
||||||
config_validation as cv,
|
config_validation as cv,
|
||||||
@ -102,12 +102,29 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
|||||||
# Note: asyncio.TimeoutError and aiohttp.ClientError are already
|
# Note: asyncio.TimeoutError and aiohttp.ClientError are already
|
||||||
# handled by the data update coordinator.
|
# handled by the data update coordinator.
|
||||||
async with async_timeout.timeout(10):
|
async with async_timeout.timeout(10):
|
||||||
module_data = await api.async_get_modules()
|
return await api.async_get_modules()
|
||||||
except HomePlusControlApiError as err:
|
except HomePlusControlApiError as err:
|
||||||
raise UpdateFailed(
|
raise UpdateFailed(
|
||||||
f"Error communicating with API: {err} [{type(err)}]"
|
f"Error communicating with API: {err} [{type(err)}]"
|
||||||
) from err
|
) from err
|
||||||
|
|
||||||
|
coordinator = DataUpdateCoordinator(
|
||||||
|
hass,
|
||||||
|
_LOGGER,
|
||||||
|
# Name of the data. For logging purposes.
|
||||||
|
name="home_plus_control_module",
|
||||||
|
update_method=async_update_data,
|
||||||
|
# Polling interval. Will only be polled if there are subscribers.
|
||||||
|
update_interval=timedelta(seconds=300),
|
||||||
|
)
|
||||||
|
hass_entry_data[DATA_COORDINATOR] = coordinator
|
||||||
|
|
||||||
|
@callback
|
||||||
|
def _async_update_entities():
|
||||||
|
"""Process entities and add or remove them based after an update."""
|
||||||
|
if not (module_data := coordinator.data):
|
||||||
|
return
|
||||||
|
|
||||||
# Remove obsolete entities from Home Assistant
|
# Remove obsolete entities from Home Assistant
|
||||||
entity_uids_to_remove = uids - set(module_data)
|
entity_uids_to_remove = uids - set(module_data)
|
||||||
for uid in entity_uids_to_remove:
|
for uid in entity_uids_to_remove:
|
||||||
@ -126,18 +143,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
|||||||
coordinator,
|
coordinator,
|
||||||
)
|
)
|
||||||
|
|
||||||
return module_data
|
entry.async_on_unload(coordinator.async_add_listener(_async_update_entities))
|
||||||
|
|
||||||
coordinator = DataUpdateCoordinator(
|
|
||||||
hass,
|
|
||||||
_LOGGER,
|
|
||||||
# Name of the data. For logging purposes.
|
|
||||||
name="home_plus_control_module",
|
|
||||||
update_method=async_update_data,
|
|
||||||
# Polling interval. Will only be polled if there are subscribers.
|
|
||||||
update_interval=timedelta(seconds=300),
|
|
||||||
)
|
|
||||||
hass_entry_data[DATA_COORDINATOR] = coordinator
|
|
||||||
|
|
||||||
async def start_platforms():
|
async def start_platforms():
|
||||||
"""Continue setting up the platforms."""
|
"""Continue setting up the platforms."""
|
||||||
|
@ -85,8 +85,18 @@ def async_dispatcher_send(hass: HomeAssistant, signal: str, *args: Any) -> None:
|
|||||||
This method must be run in the event loop.
|
This method must be run in the event loop.
|
||||||
"""
|
"""
|
||||||
target_list = hass.data.get(DATA_DISPATCHER, {}).get(signal, {})
|
target_list = hass.data.get(DATA_DISPATCHER, {}).get(signal, {})
|
||||||
|
|
||||||
|
run: list[HassJob] = []
|
||||||
for target, job in target_list.items():
|
for target, job in target_list.items():
|
||||||
if job is None:
|
if job is None:
|
||||||
job = _generate_job(signal, target)
|
job = _generate_job(signal, target)
|
||||||
target_list[target] = job
|
target_list[target] = job
|
||||||
hass.async_add_hass_job(job, *args)
|
|
||||||
|
# Run the jobs all at the end
|
||||||
|
# to ensure no jobs add more disptachers
|
||||||
|
# which can result in the target_list
|
||||||
|
# changing size during iteration
|
||||||
|
run.append(job)
|
||||||
|
|
||||||
|
for job in run:
|
||||||
|
hass.async_run_hass_job(job, *args)
|
||||||
|
@ -379,7 +379,21 @@ async def test_wireless_client_event_calls_update_wireless_devices(
|
|||||||
hass, aioclient_mock, mock_unifi_websocket
|
hass, aioclient_mock, mock_unifi_websocket
|
||||||
):
|
):
|
||||||
"""Call update_wireless_devices method when receiving wireless client event."""
|
"""Call update_wireless_devices method when receiving wireless client event."""
|
||||||
await setup_unifi_integration(hass, aioclient_mock)
|
client_1_dict = {
|
||||||
|
"essid": "ssid",
|
||||||
|
"disabled": False,
|
||||||
|
"hostname": "client_1",
|
||||||
|
"ip": "10.0.0.4",
|
||||||
|
"is_wired": False,
|
||||||
|
"last_seen": dt_util.as_timestamp(dt_util.utcnow()),
|
||||||
|
"mac": "00:00:00:00:00:01",
|
||||||
|
}
|
||||||
|
await setup_unifi_integration(
|
||||||
|
hass,
|
||||||
|
aioclient_mock,
|
||||||
|
clients_response=[client_1_dict],
|
||||||
|
known_wireless_clients=(client_1_dict["mac"],),
|
||||||
|
)
|
||||||
|
|
||||||
with patch(
|
with patch(
|
||||||
"homeassistant.components.unifi.controller.UniFiController.update_wireless_clients",
|
"homeassistant.components.unifi.controller.UniFiController.update_wireless_clients",
|
||||||
@ -391,6 +405,7 @@ async def test_wireless_client_event_calls_update_wireless_devices(
|
|||||||
"data": [
|
"data": [
|
||||||
{
|
{
|
||||||
"datetime": "2020-01-20T19:37:04Z",
|
"datetime": "2020-01-20T19:37:04Z",
|
||||||
|
"user": "00:00:00:00:00:01",
|
||||||
"key": aiounifi.events.WIRELESS_CLIENT_CONNECTED,
|
"key": aiounifi.events.WIRELESS_CLIENT_CONNECTED,
|
||||||
"msg": "User[11:22:33:44:55:66] has connected to WLAN",
|
"msg": "User[11:22:33:44:55:66] has connected to WLAN",
|
||||||
"time": 1579549024893,
|
"time": 1579549024893,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user