mirror of
https://github.com/home-assistant/core.git
synced 2025-07-13 08:17:08 +00:00
Add the ability to create Debouncer tasks as background tasks (#113128)
* Add the ability to Debouncer tasks in the background This is a more general solution as a followup to https://github.com/home-assistant/core/pull/112652#discussion_r1517159607 * Add the ability to Debouncer tasks in the background This is a more general solution as a followup to https://github.com/home-assistant/core/pull/112652#discussion_r1517159607 * fix
This commit is contained in:
parent
b3dedb3efb
commit
120525e94f
@ -23,6 +23,7 @@ class Debouncer(Generic[_R_co]):
|
|||||||
cooldown: float,
|
cooldown: float,
|
||||||
immediate: bool,
|
immediate: bool,
|
||||||
function: Callable[[], _R_co] | None = None,
|
function: Callable[[], _R_co] | None = None,
|
||||||
|
background: bool = False,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Initialize debounce.
|
"""Initialize debounce.
|
||||||
|
|
||||||
@ -38,6 +39,7 @@ class Debouncer(Generic[_R_co]):
|
|||||||
self._timer_task: asyncio.TimerHandle | None = None
|
self._timer_task: asyncio.TimerHandle | None = None
|
||||||
self._execute_at_end_of_timer: bool = False
|
self._execute_at_end_of_timer: bool = False
|
||||||
self._execute_lock = asyncio.Lock()
|
self._execute_lock = asyncio.Lock()
|
||||||
|
self._background = background
|
||||||
self._job: HassJob[[], _R_co] | None = (
|
self._job: HassJob[[], _R_co] | None = (
|
||||||
None
|
None
|
||||||
if function is None
|
if function is None
|
||||||
@ -109,7 +111,9 @@ class Debouncer(Generic[_R_co]):
|
|||||||
|
|
||||||
assert self._job is not None
|
assert self._job is not None
|
||||||
try:
|
try:
|
||||||
if task := self.hass.async_run_hass_job(self._job):
|
if task := self.hass.async_run_hass_job(
|
||||||
|
self._job, background=self._background
|
||||||
|
):
|
||||||
await task
|
await task
|
||||||
finally:
|
finally:
|
||||||
self._schedule_timer()
|
self._schedule_timer()
|
||||||
@ -130,7 +134,9 @@ class Debouncer(Generic[_R_co]):
|
|||||||
return
|
return
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if task := self.hass.async_run_hass_job(self._job):
|
if task := self.hass.async_run_hass_job(
|
||||||
|
self._job, background=self._background
|
||||||
|
):
|
||||||
await task
|
await task
|
||||||
except Exception: # pylint: disable=broad-except
|
except Exception: # pylint: disable=broad-except
|
||||||
self.logger.exception("Unexpected exception from %s", self.function)
|
self.logger.exception("Unexpected exception from %s", self.function)
|
||||||
@ -157,13 +163,18 @@ class Debouncer(Generic[_R_co]):
|
|||||||
def _on_debounce(self) -> None:
|
def _on_debounce(self) -> None:
|
||||||
"""Create job task, but only if pending."""
|
"""Create job task, but only if pending."""
|
||||||
self._timer_task = None
|
self._timer_task = None
|
||||||
if self._execute_at_end_of_timer:
|
if not self._execute_at_end_of_timer:
|
||||||
self._execute_at_end_of_timer = False
|
return
|
||||||
|
self._execute_at_end_of_timer = False
|
||||||
|
name = f"debouncer {self._job} finish cooldown={self.cooldown}, immediate={self.immediate}"
|
||||||
|
if not self._background:
|
||||||
self.hass.async_create_task(
|
self.hass.async_create_task(
|
||||||
self._handle_timer_finish(),
|
self._handle_timer_finish(), name, eager_start=True
|
||||||
f"debouncer {self._job} finish cooldown={self.cooldown}, immediate={self.immediate}",
|
|
||||||
eager_start=True,
|
|
||||||
)
|
)
|
||||||
|
return
|
||||||
|
self.hass.async_create_background_task(
|
||||||
|
self._handle_timer_finish(), name, eager_start=True
|
||||||
|
)
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def _schedule_timer(self) -> None:
|
def _schedule_timer(self) -> None:
|
||||||
|
@ -497,3 +497,35 @@ async def test_shutdown(hass: HomeAssistant, caplog: pytest.LogCaptureFixture) -
|
|||||||
|
|
||||||
assert len(calls) == 1
|
assert len(calls) == 1
|
||||||
assert debouncer._timer_task is None
|
assert debouncer._timer_task is None
|
||||||
|
|
||||||
|
|
||||||
|
async def test_background(
|
||||||
|
hass: HomeAssistant, caplog: pytest.LogCaptureFixture
|
||||||
|
) -> None:
|
||||||
|
"""Test background tasks are created when background is True."""
|
||||||
|
calls = []
|
||||||
|
|
||||||
|
async def _func() -> None:
|
||||||
|
await asyncio.sleep(0.1)
|
||||||
|
calls.append(None)
|
||||||
|
|
||||||
|
debouncer = debounce.Debouncer(
|
||||||
|
hass, _LOGGER, cooldown=0.05, immediate=True, function=_func, background=True
|
||||||
|
)
|
||||||
|
|
||||||
|
await debouncer.async_call()
|
||||||
|
assert len(calls) == 1
|
||||||
|
|
||||||
|
debouncer.async_schedule_call()
|
||||||
|
assert len(calls) == 1
|
||||||
|
|
||||||
|
async_fire_time_changed(hass, utcnow() + timedelta(seconds=1))
|
||||||
|
await hass.async_block_till_done(wait_background_tasks=False)
|
||||||
|
assert len(calls) == 1
|
||||||
|
|
||||||
|
await hass.async_block_till_done(wait_background_tasks=True)
|
||||||
|
assert len(calls) == 2
|
||||||
|
|
||||||
|
async_fire_time_changed(hass, utcnow() + timedelta(seconds=1))
|
||||||
|
await hass.async_block_till_done(wait_background_tasks=False)
|
||||||
|
assert len(calls) == 2
|
||||||
|
Loading…
x
Reference in New Issue
Block a user