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] = {}
needed: 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:
int_or_fut: Integration | asyncio.Future[None] | None = cache.get(
domain, _UNDEF
)
if isinstance(int_or_fut, asyncio.Future):
in_progress[domain] = int_or_fut
int_or_fut = cache.get(domain, _UNDEF)
# Integration is never subclassed, so we can check for type
if type(int_or_fut) is Integration: # pylint: disable=unidiomatic-typecheck
results[domain] = int_or_fut
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:
results[domain] = ValueError(f"Invalid domain {domain}")
else:
@ -915,19 +916,21 @@ async def async_get_integrations(
else:
results[domain] = cast(Integration, int_or_fut)
# First we look for custom components
if needed:
# 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)
if not needed:
return results
for domain in results:
if domain in needed:
del needed[domain]
# First we look for custom components
# 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:
if domain in needed:
del needed[domain]
# Now the rest use resolve_from_root
if needed: