Improve performance of waiting for after dependencies and device config entries (#110902)

To wait for after dependencies we created a task to wait an asyncio.Event object,
instead of using an Event we can use an asyncio.Future instead and avoid the need
for a task wrapper
This commit is contained in:
J. Nick Koston 2024-02-19 03:28:50 -06:00 committed by GitHub
parent a21d65d025
commit 4bc28489c5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 11 additions and 11 deletions

View File

@ -1741,8 +1741,8 @@ class ConfigEntries:
Config entries which are created after Home Assistant is started can't be waited Config entries which are created after Home Assistant is started can't be waited
for, the function will just return if the config entry is loaded or not. for, the function will just return if the config entry is loaded or not.
""" """
if setup_event := self.hass.data.get(DATA_SETUP_DONE, {}).get(entry.domain): if setup_future := self.hass.data.get(DATA_SETUP_DONE, {}).get(entry.domain):
await setup_event.wait() await setup_future
# The component was not loaded. # The component was not loaded.
if entry.domain not in self.hass.config.components: if entry.domain not in self.hass.config.components:
return False return False

View File

@ -43,7 +43,7 @@ BASE_PLATFORMS = {platform.value for platform in Platform}
# the task returned True. # the task returned True.
DATA_SETUP = "setup_tasks" DATA_SETUP = "setup_tasks"
# DATA_SETUP_DONE is a dict [str, asyncio.Event], indicating components which # DATA_SETUP_DONE is a dict [str, asyncio.Future], indicating components which
# will be setup: # will be setup:
# - Events are added to DATA_SETUP_DONE during bootstrap by # - Events are added to DATA_SETUP_DONE during bootstrap by
# async_set_domains_to_be_loaded, the key is the domain which will be loaded. # async_set_domains_to_be_loaded, the key is the domain which will be loaded.
@ -117,7 +117,9 @@ def async_set_domains_to_be_loaded(hass: core.HomeAssistant, domains: set[str])
- Keep track of domains which will load but have not yet finished loading - Keep track of domains which will load but have not yet finished loading
""" """
hass.data.setdefault(DATA_SETUP_DONE, {}) hass.data.setdefault(DATA_SETUP_DONE, {})
hass.data[DATA_SETUP_DONE].update({domain: asyncio.Event() for domain in domains}) hass.data[DATA_SETUP_DONE].update(
{domain: hass.loop.create_future() for domain in domains}
)
def setup_component(hass: core.HomeAssistant, domain: str, config: ConfigType) -> bool: def setup_component(hass: core.HomeAssistant, domain: str, config: ConfigType) -> bool:
@ -155,8 +157,8 @@ async def async_setup_component(
future.set_exception(err) future.set_exception(err)
raise raise
finally: finally:
if domain in hass.data.get(DATA_SETUP_DONE, {}): if future := hass.data.get(DATA_SETUP_DONE, {}).pop(domain, None):
hass.data[DATA_SETUP_DONE].pop(domain).set() future.set_result(None)
async def _async_process_dependencies( async def _async_process_dependencies(
@ -172,17 +174,15 @@ async def _async_process_dependencies(
if dep not in hass.config.components if dep not in hass.config.components
} }
after_dependencies_tasks = {} after_dependencies_tasks: dict[str, asyncio.Future[None]] = {}
to_be_loaded = hass.data.get(DATA_SETUP_DONE, {}) to_be_loaded: dict[str, asyncio.Future[None]] = hass.data.get(DATA_SETUP_DONE, {})
for dep in integration.after_dependencies: for dep in integration.after_dependencies:
if ( if (
dep not in dependencies_tasks dep not in dependencies_tasks
and dep in to_be_loaded and dep in to_be_loaded
and dep not in hass.config.components and dep not in hass.config.components
): ):
after_dependencies_tasks[dep] = hass.loop.create_task( after_dependencies_tasks[dep] = to_be_loaded[dep]
to_be_loaded[dep].wait()
)
if not dependencies_tasks and not after_dependencies_tasks: if not dependencies_tasks and not after_dependencies_tasks:
return [] return []