Avoid overloading the executor with service.yaml loads (#42172)

pull/42236/head
J. Nick Koston 2020-10-21 15:24:50 -05:00 committed by GitHub
parent 43aaf91799
commit 4a0d18ccd8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 23 additions and 11 deletions

View File

@ -38,7 +38,7 @@ from homeassistant.helpers import template
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.template import Template
from homeassistant.helpers.typing import ConfigType, HomeAssistantType, TemplateVarsType
from homeassistant.loader import async_get_integration, bind_hass
from homeassistant.loader import Integration, async_get_integration, bind_hass
from homeassistant.util.yaml import load_yaml
from homeassistant.util.yaml.loader import JSON_TYPE
@ -252,21 +252,29 @@ async def async_extract_entity_ids(
return extracted
async def _load_services_file(hass: HomeAssistantType, domain: str) -> JSON_TYPE:
def _load_services_file(hass: HomeAssistantType, integration: Integration) -> JSON_TYPE:
"""Load services file for an integration."""
integration = await async_get_integration(hass, domain)
try:
return await hass.async_add_executor_job(
load_yaml, str(integration.file_path / "services.yaml")
)
return load_yaml(str(integration.file_path / "services.yaml"))
except FileNotFoundError:
_LOGGER.warning("Unable to find services.yaml for the %s integration", domain)
_LOGGER.warning(
"Unable to find services.yaml for the %s integration", integration.domain
)
return {}
except HomeAssistantError:
_LOGGER.warning("Unable to parse services.yaml for the %s integration", domain)
_LOGGER.warning(
"Unable to parse services.yaml for the %s integration", integration.domain
)
return {}
def _load_services_files(
hass: HomeAssistantType, integrations: Iterable[Integration]
) -> List[JSON_TYPE]:
"""Load service files for multiple intergrations."""
return [_load_services_file(hass, integration) for integration in integrations]
@bind_hass
async def async_get_all_descriptions(
hass: HomeAssistantType,
@ -289,8 +297,12 @@ async def async_get_all_descriptions(
loaded = {}
if missing:
contents = await asyncio.gather(
*(_load_services_file(hass, domain) for domain in missing)
integrations = await asyncio.gather(
*(async_get_integration(hass, domain) for domain in missing)
)
contents = await hass.async_add_executor_job(
_load_services_files, hass, integrations
)
for domain, content in zip(missing, contents):
@ -308,7 +320,7 @@ async def async_get_all_descriptions(
# Cache missing descriptions
if description is None:
domain_yaml = loaded[domain]
yaml_description = domain_yaml.get(service, {})
yaml_description = domain_yaml.get(service, {}) # type: ignore
# Don't warn for missing services, because it triggers false
# positives for things like scripts, that register as a service