Prevent parallel reload of automations (#50008)

This commit is contained in:
Erik Montnemery
2021-05-25 17:50:50 +02:00
committed by GitHub
parent d2804433d3
commit 7b5e63132c
2 changed files with 51 additions and 2 deletions

View File

@@ -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()