1 """Ratelimit helper."""
3 from __future__
import annotations
6 from collections.abc
import Callable, Hashable
12 _LOGGER = logging.getLogger(__name__)
16 """Class to track rate limits."""
22 """Initialize ratelimit tracker."""
24 self._last_triggered: dict[Hashable, float] = {}
25 self._rate_limit_timers: dict[Hashable, asyncio.TimerHandle] = {}
29 """Check if a rate limit timer is running."""
30 return key
in self._rate_limit_timers
34 """Call when the action we are tracking was triggered."""
36 self._last_triggered[key] = now
or time.time()
40 """Cancel a rate limit time that will call the action."""
41 if handle := self._rate_limit_timers.pop(key,
None):
46 """Remove all timers."""
47 for timer
in self._rate_limit_timers.values():
49 self._rate_limit_timers.clear()
52 def async_schedule_action[*_Ts](
55 rate_limit: float |
None,
57 action: Callable[[*_Ts],
None],
60 """Check rate limits and schedule an action if we hit the limit.
62 If the rate limit is hit:
63 Schedules the action for when the rate limit expires
64 if there are no pending timers. The action must
67 Returns the time the rate limit will expire
69 If the rate limit is not hit:
73 if rate_limit
is None:
76 if not (last_triggered := self._last_triggered.
get(key)):
79 next_call_time = last_triggered + rate_limit
81 if next_call_time <= now:
86 "Reached rate limit of %s for %s and deferred action until %s",
92 if key
not in self._rate_limit_timers:
93 self._rate_limit_timers[key] = self.
hasshass.loop.call_later(
None __init__(self, HomeAssistant hass)
None async_triggered(self, Hashable key, float|None now=None)
bool async_has_timer(self, Hashable key)
None async_cancel_timer(self, Hashable key)
web.Response get(self, web.Request request, str config_key)