Preload platform integrations to better group executor usage (#112010)

pull/112097/head
J. Nick Koston 2024-03-02 23:03:35 -10:00 committed by GitHub
parent c8cb0ff61d
commit 6a243d6705
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 68 additions and 5 deletions

View File

@ -675,6 +675,9 @@ async def _async_resolve_domains_to_setup(
base_platforms_loaded = False
domains_to_setup = _get_domains(hass, config)
needed_requirements: set[str] = set()
platform_integrations = conf_util.extract_platform_integrations(
config, BASE_PLATFORMS
)
# Resolve all dependencies so we know all integrations
# that will have to be loaded and start rightaway
@ -691,7 +694,7 @@ async def _async_resolve_domains_to_setup(
# to avoid the lock contention when multiple
# integrations try to resolve them at once
base_platforms_loaded = True
to_get = {*old_to_resolve, *BASE_PLATFORMS}
to_get = {*old_to_resolve, *BASE_PLATFORMS, *platform_integrations}
else:
to_get = old_to_resolve
@ -700,13 +703,16 @@ async def _async_resolve_domains_to_setup(
integrations_to_process: list[loader.Integration] = []
for domain, itg in (await loader.async_get_integrations(hass, to_get)).items():
if not isinstance(itg, loader.Integration) or domain not in old_to_resolve:
if not isinstance(itg, loader.Integration):
continue
integrations_to_process.append(itg)
integration_cache[domain] = itg
needed_requirements.update(itg.requirements)
if domain not in old_to_resolve:
continue
integrations_to_process.append(itg)
manifest_deps.update(itg.dependencies)
manifest_deps.update(itg.after_dependencies)
needed_requirements.update(itg.requirements)
if not itg.all_dependencies_resolved:
resolve_dependencies_tasks.append(
create_eager_task(
@ -760,7 +766,9 @@ async def _async_resolve_domains_to_setup(
# wait for the translation load lock, loading will be done by the
# time it gets to it.
hass.async_create_background_task(
translation.async_load_integrations(hass, {*BASE_PLATFORMS, *domains_to_setup}),
translation.async_load_integrations(
hass, {*BASE_PLATFORMS, *platform_integrations, *domains_to_setup}
),
"load translations",
eager_start=True,
)

View File

@ -1388,6 +1388,30 @@ def config_per_platform(
yield platform, item
def extract_platform_integrations(config: ConfigType, domains: set[str]) -> set[str]:
"""Find all the platforms in a configuration."""
platform_integrations: set[str] = set()
for key, domain_config in config.items():
try:
domain = cv.domain_key(key)
except vol.Invalid:
continue
if domain not in domains:
continue
if not isinstance(domain_config, list):
domain_config = [domain_config]
for item in domain_config:
try:
platform = item.get(CONF_PLATFORM)
except AttributeError:
continue
if platform:
platform_integrations.add(platform)
return platform_integrations
def extract_domain_configs(config: ConfigType, domain: str) -> Sequence[str]:
"""Extract keys from config for given domain name.

View File

@ -2339,3 +2339,34 @@ def test_config_per_platform() -> None:
(None, 1),
("hello 2", config["zone Hallo"][1]),
] == list(config_util.config_per_platform(config, "zone"))
def test_extract_platform_integrations() -> None:
"""Test extract_platform_integrations."""
config = OrderedDict(
[
(b"zone", {"platform": "not str"}),
("zone", {"platform": "hello"}),
("zonex", []),
("zoney", ""),
("notzone", {"platform": "nothello"}),
("zoner", None),
("zone Hallo", [1, {"platform": "hello 2"}]),
("zone 100", None),
("i n v a-@@", None),
("i n v a-@@", {"platform": "hello"}),
("zoneq", "pig"),
("zoneempty", {"platform": ""}),
]
)
assert config_util.extract_platform_integrations(config, {"zone"}) == {
"hello",
"hello 2",
}
assert config_util.extract_platform_integrations(config, {"zonex"}) == set()
assert config_util.extract_platform_integrations(config, {"zoney"}) == set()
assert config_util.extract_platform_integrations(
config, {"zone", "not_valid", "notzone"}
) == {"hello", "hello 2", "nothello"}
assert config_util.extract_platform_integrations(config, {"zoneq"}) == set()
assert config_util.extract_platform_integrations(config, {"zoneempty"}) == set()