core/homeassistant/helpers/start.py

93 lines
2.6 KiB
Python
Raw Normal View History

"""Helpers to help during startup."""
from __future__ import annotations
from collections.abc import Callable, Coroutine
from typing import Any
2022-10-05 10:24:51 +00:00
from homeassistant.const import EVENT_HOMEASSISTANT_START, EVENT_HOMEASSISTANT_STARTED
from homeassistant.core import (
CALLBACK_TYPE,
CoreState,
Event,
HassJob,
HomeAssistant,
callback,
)
from homeassistant.util.event_type import EventType
from .typing import NoEventData
@callback
2022-10-05 10:24:51 +00:00
def _async_at_core_state(
hass: HomeAssistant,
at_start_cb: Callable[[HomeAssistant], Coroutine[Any, Any, None] | None],
event_type: EventType[NoEventData],
2022-10-05 10:24:51 +00:00
check_state: Callable[[HomeAssistant], bool],
) -> CALLBACK_TYPE:
2022-10-05 10:24:51 +00:00
"""Execute a job at_start_cb when Home Assistant has the wanted state.
2022-10-05 10:24:51 +00:00
The job is executed immediately if Home Assistant is in the wanted state.
Will wait for event specified by event_type if it isn't.
"""
at_start_job = HassJob(at_start_cb)
2022-10-05 10:24:51 +00:00
if check_state(hass):
Run coroutines as eager tasks in async_run_hass_job (#111683) * Run coroutines as eager tasks in async_run_hass_job Note that this does not change async_add_hass_job Do not merge this. For test run only * Phase out periodic tasks * false by default or some tests will block forever, will need to fix each one manually * kwarg works * kwarg works * kwarg works * fixes * fix more tests * fix more tests * fix lifx * opensky * pvpc_hourly_pricing * adjust more * adjust more * smarttub * adjust more * adjust more * adjust more * adjust more * adjust * no eager executor * zha * qnap_qsw * fix more * fix fix * docs * its a wrapper now * add more coverage * coverage * cover all combos * more fixes * more fixes * more fixes * remaining issues are legit bugs in tests * make tplink test more predictable * more fixes * feedreader * grind out some more * make test race safe * limit first scope to triggers * one more * Start tasks eagerly in for async_at_start(ed) A few of these can avoid being scheduled on the loop during startup * fix cloud * Revert "fix cloud" This reverts commit 5eb3ce695da788bcae649f82c9527c0f9307139c. * fix test to do what start does * flip flag * flip flag * Fix here_travel_time creating many refresh requests at startup - Each entity would try to refresh the coordinator which created many tasks. Move the refresh to a single async_at_started - The tests fired the EVENT_HOMEASSISTANT_START event but the code used async_at_started which only worked because the tests did not set CoreState to not_running * fix azure * remove kw * remove kw * rip * cover * more rips * more rips * more rips
2024-03-12 00:05:08 +00:00
hass.async_run_hass_job(at_start_job, hass)
return lambda: None
2024-05-24 13:05:53 +00:00
unsub: CALLBACK_TYPE | None = None
@callback
def _matched_event(event: Event) -> None:
"""Call the callback when Home Assistant started."""
Run coroutines as eager tasks in async_run_hass_job (#111683) * Run coroutines as eager tasks in async_run_hass_job Note that this does not change async_add_hass_job Do not merge this. For test run only * Phase out periodic tasks * false by default or some tests will block forever, will need to fix each one manually * kwarg works * kwarg works * kwarg works * fixes * fix more tests * fix more tests * fix lifx * opensky * pvpc_hourly_pricing * adjust more * adjust more * smarttub * adjust more * adjust more * adjust more * adjust more * adjust * no eager executor * zha * qnap_qsw * fix more * fix fix * docs * its a wrapper now * add more coverage * coverage * cover all combos * more fixes * more fixes * more fixes * remaining issues are legit bugs in tests * make tplink test more predictable * more fixes * feedreader * grind out some more * make test race safe * limit first scope to triggers * one more * Start tasks eagerly in for async_at_start(ed) A few of these can avoid being scheduled on the loop during startup * fix cloud * Revert "fix cloud" This reverts commit 5eb3ce695da788bcae649f82c9527c0f9307139c. * fix test to do what start does * flip flag * flip flag * Fix here_travel_time creating many refresh requests at startup - Each entity would try to refresh the coordinator which created many tasks. Move the refresh to a single async_at_started - The tests fired the EVENT_HOMEASSISTANT_START event but the code used async_at_started which only worked because the tests did not set CoreState to not_running * fix azure * remove kw * remove kw * rip * cover * more rips * more rips * more rips
2024-03-12 00:05:08 +00:00
hass.async_run_hass_job(at_start_job, hass)
nonlocal unsub
unsub = None
@callback
def cancel() -> None:
if unsub:
unsub()
unsub = hass.bus.async_listen_once(event_type, _matched_event)
return cancel
2022-10-05 10:24:51 +00:00
@callback
def async_at_start(
hass: HomeAssistant,
at_start_cb: Callable[[HomeAssistant], Coroutine[Any, Any, None] | None],
) -> CALLBACK_TYPE:
"""Execute a job at_start_cb when Home Assistant is starting.
The job is executed immediately if Home Assistant is already starting or started.
Will wait for EVENT_HOMEASSISTANT_START if it isn't.
"""
def _is_running(hass: HomeAssistant) -> bool:
return hass.is_running
return _async_at_core_state(
hass, at_start_cb, EVENT_HOMEASSISTANT_START, _is_running
)
@callback
def async_at_started(
hass: HomeAssistant,
at_start_cb: Callable[[HomeAssistant], Coroutine[Any, Any, None] | None],
) -> CALLBACK_TYPE:
"""Execute a job at_start_cb when Home Assistant has started.
The job is executed immediately if Home Assistant is already started.
Will wait for EVENT_HOMEASSISTANT_STARTED if it isn't.
"""
def _is_started(hass: HomeAssistant) -> bool:
return hass.state is CoreState.running
2022-10-05 10:24:51 +00:00
return _async_at_core_state(
hass, at_start_cb, EVENT_HOMEASSISTANT_STARTED, _is_started
)