mirror of
https://github.com/home-assistant/core.git
synced 2025-07-24 21:57:51 +00:00
Prevent parallel reload of automations (#50008)
This commit is contained in:
parent
d2804433d3
commit
7b5e63132c
@ -54,7 +54,10 @@ from homeassistant.helpers.script import (
|
|||||||
Script,
|
Script,
|
||||||
)
|
)
|
||||||
from homeassistant.helpers.script_variables import ScriptVariables
|
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 (
|
from homeassistant.helpers.trace import (
|
||||||
TraceElement,
|
TraceElement,
|
||||||
script_execution_set,
|
script_execution_set,
|
||||||
@ -253,8 +256,14 @@ async def async_setup(hass, config):
|
|||||||
await _async_process_config(hass, conf, component)
|
await _async_process_config(hass, conf, component)
|
||||||
hass.bus.async_fire(EVENT_AUTOMATION_RELOADED, context=service_call.context)
|
hass.bus.async_fire(EVENT_AUTOMATION_RELOADED, context=service_call.context)
|
||||||
|
|
||||||
|
reload_helper = ReloadServiceHelper(reload_service_handler)
|
||||||
|
|
||||||
async_register_admin_service(
|
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
|
return True
|
||||||
|
@ -783,3 +783,43 @@ def verify_domain_control(
|
|||||||
return check_permissions
|
return check_permissions
|
||||||
|
|
||||||
return decorator
|
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…
x
Reference in New Issue
Block a user