Skip to content

Commit f1921e7

Browse files
committed
Add rate calc
1 parent ce0ee2e commit f1921e7

File tree

3 files changed

+62
-2
lines changed

3 files changed

+62
-2
lines changed

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
setuptools.setup(
77
name="tesla_fleet_api",
8-
version="0.7.2",
8+
version="0.7.3",
99
author="Brett Adams",
1010
author_email="[email protected]",
1111
description="Tesla Fleet API library for Python",

tesla_fleet_api/const.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from enum import Enum
44
import logging
55

6-
VERSION = "0.7.2"
6+
VERSION = "0.7.3"
77
LOGGER = logging.getLogger(__package__)
88
SERVERS = {
99
"na": "https://fleet-api.prd.na.vn.cloud.tesla.com",

tesla_fleet_api/ratecalculator.py

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
"""Rate Calculator helper"""
2+
3+
import time
4+
5+
DAY = 24 * 60 * 60
6+
7+
8+
class RateCalculator:
9+
"""Calculate the consumption and remaining rate of a rate limit."""
10+
11+
def __init__(
12+
self,
13+
limit: int,
14+
period: int = 86400,
15+
min_wait: int = 0,
16+
max_wait: int | None = None,
17+
factor: int = 5,
18+
) -> None:
19+
"""Initialize the rate calculator."""
20+
self.limit: int = limit
21+
self.period: int = period
22+
self.history: list[int] = []
23+
self.start = time.time()
24+
self.min_wait = min_wait
25+
self.max_wait = max_wait if max_wait is not None else period
26+
self.factor = factor
27+
28+
def constrain(self, value: float) -> float:
29+
"""Constrain a value between min and max."""
30+
return max(self.min_wait, min(self.max_wait, value))
31+
32+
def consume(self, timestamp: int | None = None) -> None:
33+
"""Consume a unit of the rate limit."""
34+
now = timestamp or int(time.time() + 1)
35+
self.history.append(now)
36+
37+
def calculate(self, timestamp: int | None = None) -> float:
38+
"""Return the ideal delay to avoid rate limiting."""
39+
40+
count = len(self.history)
41+
if count == 0:
42+
return self.min_wait
43+
44+
now = timestamp or int(time.time())
45+
46+
while self.history and self.history[0] < now - self.period:
47+
self.history.pop(0)
48+
49+
remaining = self.limit - count
50+
51+
if remaining <= 0:
52+
# The wait until a request is available
53+
return self.constrain(self.history[abs(remaining)] + self.period - now)
54+
55+
return self.constrain(self.period / remaining / self.factor)
56+
57+
@property
58+
def count(self) -> int:
59+
"""Return the number of requests in the current period."""
60+
return len(self.history)

0 commit comments

Comments
 (0)