Reduce overhead to fetch integrations (#93767)

We call this path over and over during startup and most
of the time the integration is already loaded. We want
that case to be the short path
This commit is contained in:
J. Nick Koston 2023-05-29 19:58:51 -05:00 committed by GitHub
parent 1ea202a5bc
commit 53fe74e055
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -891,14 +891,15 @@ async def async_get_integrations(
results: dict[str, Integration | Exception] = {} results: dict[str, Integration | Exception] = {}
needed: dict[str, asyncio.Future[None]] = {} needed: dict[str, asyncio.Future[None]] = {}
in_progress: dict[str, asyncio.Future[None]] = {} in_progress: dict[str, asyncio.Future[None]] = {}
if TYPE_CHECKING:
cache = cast(dict[str, Integration | asyncio.Future[None]], cache)
for domain in domains: for domain in domains:
int_or_fut: Integration | asyncio.Future[None] | None = cache.get( int_or_fut = cache.get(domain, _UNDEF)
domain, _UNDEF # Integration is never subclassed, so we can check for type
) if type(int_or_fut) is Integration: # pylint: disable=unidiomatic-typecheck
if isinstance(int_or_fut, asyncio.Future): results[domain] = int_or_fut
in_progress[domain] = int_or_fut
elif int_or_fut is not _UNDEF: elif int_or_fut is not _UNDEF:
results[domain] = cast(Integration, int_or_fut) in_progress[domain] = cast(asyncio.Future[None], int_or_fut)
elif "." in domain: elif "." in domain:
results[domain] = ValueError(f"Invalid domain {domain}") results[domain] = ValueError(f"Invalid domain {domain}")
else: else:
@ -915,19 +916,21 @@ async def async_get_integrations(
else: else:
results[domain] = cast(Integration, int_or_fut) results[domain] = cast(Integration, int_or_fut)
# First we look for custom components if not needed:
if needed: return results
# Instead of using resolve_from_root we use the cache of custom
# components to find the integration.
custom = await async_get_custom_components(hass)
for domain, future in needed.items():
if integration := custom.get(domain):
results[domain] = cache[domain] = integration
future.set_result(None)
for domain in results: # First we look for custom components
if domain in needed: # Instead of using resolve_from_root we use the cache of custom
del needed[domain] # components to find the integration.
custom = await async_get_custom_components(hass)
for domain, future in needed.items():
if integration := custom.get(domain):
results[domain] = cache[domain] = integration
future.set_result(None)
for domain in results:
if domain in needed:
del needed[domain]
# Now the rest use resolve_from_root # Now the rest use resolve_from_root
if needed: if needed: