Fix thundering herd of mqtt component setup tasks (#118210)

We had a thundering herd of tasks to back up against the lock to load each MQTT platform at startup because we had to wait to import the platforms.
pull/117911/head^2
J. Nick Koston 2024-05-26 18:29:35 -10:00 committed by GitHub
parent ecb05989ca
commit 872e9f2d5e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 29 additions and 4 deletions

View File

@ -20,7 +20,12 @@ from homeassistant.exceptions import (
ServiceValidationError,
Unauthorized,
)
from homeassistant.helpers import config_validation as cv, event as ev, template
from homeassistant.helpers import (
config_validation as cv,
entity_registry as er,
event as ev,
template,
)
from homeassistant.helpers.device_registry import DeviceEntry
from homeassistant.helpers.dispatcher import async_dispatcher_connect
from homeassistant.helpers.entity_platform import async_get_platforms
@ -31,7 +36,8 @@ from homeassistant.helpers.issue_registry import (
from homeassistant.helpers.reload import async_integration_yaml_config
from homeassistant.helpers.service import async_register_admin_service
from homeassistant.helpers.typing import ConfigType
from homeassistant.loader import async_get_integration
from homeassistant.loader import async_get_integration, async_get_loaded_integration
from homeassistant.setup import SetupPhases, async_pause_setup
# Loading the config flow file will register the flow
from . import debug_info, discovery
@ -252,7 +258,6 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
entry.add_update_listener(_async_config_entry_updated)
)
await mqtt_data.client.async_connect(client_available)
return (mqtt_data, conf)
client_available: asyncio.Future[bool]
@ -262,6 +267,27 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
client_available = hass.data[DATA_MQTT_AVAILABLE]
mqtt_data, conf = await _setup_client(client_available)
platforms_used = platforms_from_config(mqtt_data.config)
platforms_used.update(
entry.domain
for entry in er.async_entries_for_config_entry(
er.async_get(hass), entry.entry_id
)
)
integration = async_get_loaded_integration(hass, DOMAIN)
# Preload platforms we know we are going to use so
# discovery can setup each platform synchronously
# and avoid creating a flood of tasks at startup
# while waiting for the the imports to complete
if not integration.platforms_are_loaded(platforms_used):
with async_pause_setup(hass, SetupPhases.WAIT_IMPORT_PLATFORMS):
await integration.async_get_platforms(platforms_used)
# Wait to connect until the platforms are loaded so
# we can be sure discovery does not have to wait for
# each platform to load when we get the flood of retained
# messages on connect
await mqtt_data.client.async_connect(client_available)
async def async_publish_service(call: ServiceCall) -> None:
"""Handle MQTT publish service calls."""
@ -392,7 +418,6 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
async_register_admin_service(hass, DOMAIN, SERVICE_RELOAD, _reload_config)
platforms_used = platforms_from_config(mqtt_data.config)
await async_forward_entry_setup_and_setup_discovery(hass, entry, platforms_used)
# Setup reload service after all platforms have loaded
await async_setup_reload_service()