Advanced¶
The rate-limiting internals. You do not need these to use the library –
AlmaClient builds and drives them for you – but they are documented because
the behaviour they implement is worth understanding when tuning rate_limit, or
when reading the almapy.throttle log output.
See Rate limiting for the narrative version.
Token bucket¶
TokenBucket
¶
TokenBucket(rate: float)
Paces requests to a fixed rate, holding one second of burst capacity.
AlmaClient builds one from its rate_limit argument, so there is rarely
a reason to construct this yourself. What it means in practice: an idle client
can fire off up to rate requests at once, and is then paced at rate per
second. Callers wait their turn in
acquire rather than being rejected,
which is why a large asyncio.gather is safe.
rate
property
writable
¶
rate: float
Current refill rate in tokens (requests) per second.
Setting it clamps the outstanding token count to the new rate, so lowering the rate takes effect immediately rather than after an accumulated burst is spent.
Raises:
| Type | Description |
|---|---|
ValueError
|
If set to zero or a negative value. |
acquire
async
¶
Consume one token, waiting for the bucket to refill if it is empty.
Never times out – it waits as long as necessary. Use
AdaptiveController.acquire
for a bounded wait.
Adaptive controller¶
AdaptiveController
¶
AdaptiveController(
bucket: TokenBucket,
max_rate: float,
*,
backoff_factor: float = 0.5,
recovery_increment: float = 1.0,
recovery_window: float = 10.0,
cooldown: float = 5.0,
max_wait: float | None = None,
min_rate: float = 1.0,
)
Adjusts a bucket's rate to match how Alma is currently behaving.
Cuts the rate sharply the moment requests start failing and restores it
gradually as they succeed, so a struggling Alma is not hammered and a healthy
one is not left throttled. AlmaClient builds and drives one of these for
you; the tuning arguments below are exposed on its constructor as
backoff_factor, recovery_increment, recovery_window, cooldown
and max_wait.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
bucket
|
TokenBucket
|
The bucket whose rate is adjusted. |
required |
max_rate
|
float
|
Ceiling for recovery, normally the configured |
required |
backoff_factor
|
float
|
What the rate is multiplied by on failure. |
0.5
|
recovery_increment
|
float
|
How much is added back per successful recovery step. |
1.0
|
recovery_window
|
float
|
Minimum interval between recovery steps, in seconds. |
10.0
|
cooldown
|
float
|
How long after a cut further failures are ignored, in seconds. |
5.0
|
max_wait
|
float | None
|
Bound on how long a caller will wait for a token before
|
None
|
min_rate
|
float
|
Floor the rate is never cut below. |
1.0
|
See Rate limiting for how this behaves in practice, and how it interacts with retries.
current_rate
property
¶
current_rate: float
The rate the underlying bucket is currently running at, in requests/second.
Read-only, and lower than the configured maximum whenever backpressure has cut it. Useful for monitoring – logging it, or exporting it as a metric.
acquire
async
¶
Wait for cooldown to elapse, then consume one token from the bucket.
Raises:
| Type | Description |
|---|---|
ThrottleTimeoutError
|
If |
record_failure
¶
Report a transient failure, cutting the rate multiplicatively.
Multiplies the rate by backoff_factor (never below min_rate) and
starts a cooldown, during which further failures are ignored – a burst of
concurrent failures from one incident cuts the rate once, not once per
request.
Called for any failure _should_retry recognises, deliberately including
those on POST and PATCH requests that will not themselves be replayed: a 5xx
says something about Alma's health whichever verb provoked it.
record_success
¶
Report a successful request, recovering the rate additively.
Adds recovery_increment to the rate, up to max_rate. Recovery is
time-gated to at most once per recovery_window and suppressed entirely
during cooldown, so the rate climbs back gradually rather than jumping
straight to the maximum after one success.