diff --git a/homeassistant/helpers/debounce.py b/homeassistant/helpers/debounce.py index b4a4cde0c1f..dd536956a83 100644 --- a/homeassistant/helpers/debounce.py +++ b/homeassistant/helpers/debounce.py @@ -94,11 +94,6 @@ class Debouncer(Generic[_R_co]): """Handle a finished timer.""" assert self._job is not None - self._timer_task = None - - if not self._execute_at_end_of_timer: - return - self._execute_at_end_of_timer = False # Locked means a call is in progress. Any call is good, so abort. @@ -108,7 +103,7 @@ class Debouncer(Generic[_R_co]): async with self._execute_lock: # Abort if timer got set while we're waiting for the lock. if self._timer_task: - return # type: ignore[unreachable] + return try: task = self.hass.async_run_hass_job(self._job) @@ -117,6 +112,7 @@ class Debouncer(Generic[_R_co]): except Exception: # pylint: disable=broad-except self.logger.exception("Unexpected exception from %s", self.function) + # Schedule a new timer to prevent new runs during cooldown self._schedule_timer() @callback @@ -129,12 +125,16 @@ class Debouncer(Generic[_R_co]): self._execute_at_end_of_timer = False @callback - def _schedule_timer(self) -> None: - """Schedule a timer.""" - self._timer_task = self.hass.loop.call_later( - self.cooldown, - lambda: self.hass.async_create_task( + def _on_debounce(self) -> None: + """Create job task, but only if pending.""" + self._timer_task = None + if self._execute_at_end_of_timer: + self.hass.async_create_task( self._handle_timer_finish(), f"debouncer {self._job} finish cooldown={self.cooldown}, immediate={self.immediate}", - ), - ) + ) + + @callback + def _schedule_timer(self) -> None: + """Schedule a timer.""" + self._timer_task = self.hass.loop.call_later(self.cooldown, self._on_debounce)