Prevent parallel reload of automations (#50008)
This commit is contained in:
parent
d2804433d3
commit
7b5e63132c
2 changed files with 51 additions and 2 deletions
|
@ -54,7 +54,10 @@ from homeassistant.helpers.script import (
|
|||
Script,
|
||||
)
|
||||
from homeassistant.helpers.script_variables import ScriptVariables
|
||||
from homeassistant.helpers.service import async_register_admin_service
|
||||
from homeassistant.helpers.service import (
|
||||
ReloadServiceHelper,
|
||||
async_register_admin_service,
|
||||
)
|
||||
from homeassistant.helpers.trace import (
|
||||
TraceElement,
|
||||
script_execution_set,
|
||||
|
@ -253,8 +256,14 @@ async def async_setup(hass, config):
|
|||
await _async_process_config(hass, conf, component)
|
||||
hass.bus.async_fire(EVENT_AUTOMATION_RELOADED, context=service_call.context)
|
||||
|
||||
reload_helper = ReloadServiceHelper(reload_service_handler)
|
||||
|
||||
async_register_admin_service(
|
||||
hass, DOMAIN, SERVICE_RELOAD, reload_service_handler, schema=vol.Schema({})
|
||||
hass,
|
||||
DOMAIN,
|
||||
SERVICE_RELOAD,
|
||||
reload_helper.execute_service,
|
||||
schema=vol.Schema({}),
|
||||
)
|
||||
|
||||
return True
|
||||
|
|
|
@ -783,3 +783,43 @@ def verify_domain_control(
|
|||
return check_permissions
|
||||
|
||||
return decorator
|
||||
|
||||
|
||||
class ReloadServiceHelper:
|
||||
"""Helper for reload services to minimize unnecessary reloads."""
|
||||
|
||||
def __init__(self, service_func: Callable[[ServiceCall], Awaitable]):
|
||||
"""Initialize ReloadServiceHelper."""
|
||||
self._service_func = service_func
|
||||
self._service_running = False
|
||||
self._service_condition = asyncio.Condition()
|
||||
|
||||
async def execute_service(self, service_call: ServiceCall) -> None:
|
||||
"""Execute the service.
|
||||
|
||||
If a previous reload task if currently in progress, wait for it to finish first.
|
||||
Once the previous reload task has finished, one of the waiting tasks will be
|
||||
assigned to execute the reload, the others will wait for the reload to finish.
|
||||
"""
|
||||
|
||||
do_reload = False
|
||||
async with self._service_condition:
|
||||
if self._service_running:
|
||||
# A previous reload task is already in progress, wait for it to finish
|
||||
await self._service_condition.wait()
|
||||
|
||||
async with self._service_condition:
|
||||
if not self._service_running:
|
||||
# This task will do the reload
|
||||
self._service_running = True
|
||||
do_reload = True
|
||||
else:
|
||||
# Another task will perform the reload, wait for it to finish
|
||||
await self._service_condition.wait()
|
||||
|
||||
if do_reload:
|
||||
# Reload, then notify other tasks
|
||||
await self._service_func(service_call)
|
||||
async with self._service_condition:
|
||||
self._service_running = False
|
||||
self._service_condition.notify_all()
|
||||
|
|
Loading…
Add table
Reference in a new issue