pyrate_limiter.abstracts package¶
- class pyrate_limiter.abstracts.AbstractBucket¶
Bases:
ABCBase bucket interface Assumption: len(rates) always > 0 TODO: allow empty rates
- close()¶
Release any resources held by the bucket.
Subclasses may override this method to perform any necessary cleanup (e.g., closing files, network connections, or releasing locks) when the bucket is no longer needed.
- Return type:
None
- abstractmethod count()¶
Count number of items in the bucket
- Return type:
int|Awaitable[int]
- failing_rate = None¶
- abstractmethod flush()¶
Flush the whole bucket - Must remove failing-rate after flushing
- Return type:
None|Awaitable[None]
- is_async = None¶
- abstractmethod leak(current_timestamp=None)¶
leaking bucket - removing items that are outdated
- Return type:
int|Awaitable[int]
- limiter_lock()¶
An additional lock to be used by Limiter in-front of the thread lock. Intended for multiprocessing environments where a thread lock is insufficient.
- Return type:
object|None
- now()¶
Retrieve current timestamp from the clock backend.
- abstractmethod peek(index)¶
Peek at the rate-item at a specific index in latest-to-earliest order NOTE: The reason we cannot peek from the start of the queue(earliest-to-latest) is we can’t really tell how many outdated items are still in the queue
- abstractmethod put(item)¶
Put an item (typically the current time) in the bucket return true if successful, otherwise false
- Return type:
bool|Awaitable[bool]
- put_decision(item)¶
put(), returning the fullDecisionrather than a bare bool.Buckets need not override it; the default reads back what
put()recorded.retry_after_msisNonefor buckets that record none.
- property rates¶
- waiting(item)¶
Calculate time until bucket become availabe to consume an item again
- Return type:
int|Awaitable[int]
- class pyrate_limiter.abstracts.Algorithm¶
Bases:
ABCA rate-limiting policy, independent of any storage backend.
Implementations must be stateless so one instance can be shared across buckets and threads. The two sub-interfaces differ in what they need remembered per key:
LogAlgorithman entry per consumed unit,StateAlgorithma fixed handful of numbers.- max_weight(rate)¶
Largest weight this policy can ever admit under
rate.- Return type:
int
- class pyrate_limiter.abstracts.BucketAsyncWrapper(bucket)¶
Bases:
AbstractBucketBucketAsyncWrapper is a wrapping over any bucket that turns a async/synchronous bucket into an async one
- async count()¶
Count number of items in the bucket
- property failing_rate¶
The type of the None singleton.
- async flush()¶
Flush the whole bucket - Must remove failing-rate after flushing
- Return type:
None
- is_async = True¶
- async leak(current_timestamp=None)¶
leaking bucket - removing items that are outdated
- Return type:
int
- now()¶
Retrieve current timestamp from the clock backend.
- Return type:
int
- async peek(index)¶
Peek at the rate-item at a specific index in latest-to-earliest order NOTE: The reason we cannot peek from the start of the queue(earliest-to-latest) is we can’t really tell how many outdated items are still in the queue
- Return type:
RateItem|None
- async put(item)¶
Put an item (typically the current time) in the bucket return true if successful, otherwise false
- property rates¶
- async waiting(item)¶
Calculate time until bucket become availabe to consume an item again
- Return type:
int
- class pyrate_limiter.abstracts.BucketFactory¶
Bases:
ABCAsbtract BucketFactory class. It is reserved for user to implement/override this class with his own bucket-routing/creating logic
- close()¶
- Return type:
None
- create(bucket_class, *args, **kwargs)¶
Creating a bucket dynamically
- Return type:
- dispose(bucket)¶
Delete a bucket from the factory
- Return type:
bool
- abstractmethod get(item)¶
Get the corresponding bucket to this item
- Return type:
AbstractBucket|Awaitable[AbstractBucket]
- get_buckets()¶
Iterator over all buckets in the factory
- Return type:
List[AbstractBucket]
- property leak_interval¶
Retrieve leak-interval from inner Leaker task
- schedule_leak(new_bucket)¶
Schedule all the buckets’ leak, reset bucket’s failing rate
- Return type:
None
- class pyrate_limiter.abstracts.Decision(failing_rate=None, retry_after_ms=None)¶
Bases:
objectOutcome of an admit check.
retry_after_msis measured from the checked item’s own timestamp.Nonemeans “unknown, askAbstractBucket.waiting()” - either the weight can never fit, or the backend does not compute a wait. It does not mean “no wait”.- property allowed¶
- failing_rate = None¶
- retry_after_ms = None¶
- class pyrate_limiter.abstracts.Duration(*values)¶
Bases:
EnumInterval helper class
- DAY = 86400000¶
- HOUR = 3600000¶
- MINUTE = 60000¶
- SECOND = 1000¶
- WEEK = 604800000¶
- static readable(value)¶
- Return type:
str
- class pyrate_limiter.abstracts.FixedWindow¶
Bases:
LogAlgorithmCounts within a wall-clock-aligned window that resets every
interval.Cheaper and coarser than the rolling window: up to
2 * limitcan pass across a window boundary. Use it to mirror an upstream API that genuinely resets on the hour rather than rolling.- admit(rates, counts, weight)¶
Whether
weightmore units fit, givencountsaligned torates.- Return type:
- retry_after(rate, now, blocking_timestamp)¶
Milliseconds until room exists under
rate.blocking_timestampis the entry named byblocking_offset(), orNonewhen there is none - or when the policy never asks for one.- Return type:
int
- window_start(rate, now)¶
Inclusive lower bound of
rate’s counting window atnow.- Return type:
int
- class pyrate_limiter.abstracts.GCRA¶
Bases:
StateAlgorithmGeneric Cell Rate Algorithm - a leaky bucket kept as one timestamp.
Tracks a theoretical arrival time (TAT) per rate: the moment the bucket would next be empty. Admitting
weightpushes the TAT forward byweight * emission_interval; the request is allowed while that stays withinburstunits ofnow.Sustains
limitperintervalwhile tolerating a burst ofrate.burst, using one number per rate instead of an entry per unit.State is integer microseconds, not fractional milliseconds. An absolute TAT in epoch ms is ~1.7e12, and accumulating a fractional emission interval onto it loses the low bits - enough that the accumulated sum of burst emissions no longer equals burst * emission, and the last unit of a full burst gets rejected by a rounding error. Integers make it exact, and stay well inside the 2**53 a Lua double holds.
- consumed(rates, state, now)¶
Units currently owed - the closest analogue to a log’s length.
- Return type:
int
- decode(values)¶
Parse persisted strings back into state.
- Return type:
Tuple[float,...]
- initial(rates)¶
State for a key that has never been used.
- Return type:
Tuple[float,...]
- max_weight(rate)¶
Largest weight this policy can ever admit under
rate.- Return type:
int
- redis_args(rates)¶
Arguments
redis_script()needs, after the standard header.The store passes these through without inspecting them, so a policy’s script and its arguments stay a matched pair that only the policy knows the shape of. The header the store supplies first is
now, weight, ttl_ms, len(rates).- Return type:
List[int|float]
- redis_script()¶
Lua implementing
step()atomically, if this policy has one.- Return type:
str|None
- class pyrate_limiter.abstracts.LogAlgorithm¶
Bases:
AlgorithmPolicy over storage holding one timestamped entry per consumed unit.
- abstractmethod admit(rates, counts, weight)¶
Whether
weightmore units fit, givencountsaligned torates.- Return type:
- blocking_offset(rate, weight)¶
Offset from the newest stored entry (0-based) whose expiry makes room for
weight, orNoneif the wait does not depend on an entry.- Return type:
int|None
- decide(rates, counts, weight, now, peek_timestamp)¶
admit(), resolving the retry-after in the same step on denial.peek_timestamp(offset)is only called when the policy asks for an entry and the item was rejected, so backends pay for the lookup only when it is needed.- Return type:
- leak_bound(rates, now)¶
Timestamp below which an entry is outside every rate’s window.
- Return type:
int
- abstractmethod retry_after(rate, now, blocking_timestamp)¶
Milliseconds until room exists under
rate.blocking_timestampis the entry named byblocking_offset(), orNonewhen there is none - or when the policy never asks for one.- Return type:
int
- abstractmethod window_start(rate, now)¶
Inclusive lower bound of
rate’s counting window atnow.- Return type:
int
- class pyrate_limiter.abstracts.Rate(limit, interval, burst=None)¶
Bases:
objectRate definition.
- Parameters:
limit (
int) – Number of requests allowed withinintervalinterval (
int|Duration) – Time interval, in milisecondsburst (
int|None) – How many units may be spent at once. Only the constant-state algorithms (GCRA,TokenBucket) read it; the window algorithms admit up tolimitper window regardless. Defaults tolimit, which is classic token-bucket behaviour - a full bucket at rest.burst=1makes the output perfectly smooth.
- burst¶
- interval¶
- limit¶
- class pyrate_limiter.abstracts.RateItem(name, timestamp, weight=1)¶
Bases:
objectRateItem is a wrapper for bucket to work with
- name¶
- timestamp¶
- weight¶
- class pyrate_limiter.abstracts.SlidingWindowLog¶
Bases:
LogAlgorithmPrecise rolling window: admit while each rate’s last
intervalstays under its limit.The default. Exact, at the cost of one stored entry per consumed unit.
- admit(rates, counts, weight)¶
Whether
weightmore units fit, givencountsaligned torates.- Return type:
- blocking_offset(rate, weight)¶
Offset from the newest stored entry (0-based) whose expiry makes room for
weight, orNoneif the wait does not depend on an entry.- Return type:
int|None
- retry_after(rate, now, blocking_timestamp)¶
Milliseconds until room exists under
rate.blocking_timestampis the entry named byblocking_offset(), orNonewhen there is none - or when the policy never asks for one.- Return type:
int
- window_start(rate, now)¶
Inclusive lower bound of
rate’s counting window atnow.- Return type:
int
- class pyrate_limiter.abstracts.StateAlgorithm¶
Bases:
AlgorithmPolicy whose state is a fixed-size tuple of numbers, not a log.
Storage keeps one small value per key however much traffic passes, and the wait comes out in closed form. In exchange the check is destructive - it spends what it admits - so
step()must evaluate every rate before committing any of them.- consumed(rates, state, now)¶
Units currently owed - the closest analogue to a log’s length.
- Return type:
int
- decode(values)¶
Parse persisted strings back into state.
- Return type:
Tuple[float,...]
- abstractmethod initial(rates)¶
State for a key that has never been used.
- Return type:
Tuple[float,...]
- redis_args(rates)¶
Arguments
redis_script()needs, after the standard header.The store passes these through without inspecting them, so a policy’s script and its arguments stay a matched pair that only the policy knows the shape of. The header the store supplies first is
now, weight, ttl_ms, len(rates).- Return type:
List[int|float]
- redis_script()¶
Lua implementing
step()atomically, if this policy has one.- Return type:
str|None
- class pyrate_limiter.abstracts.StateStore¶
Bases:
ABCHolds one key’s state for a
StateAlgorithm.The store’s only real job is atomicity:
check()must read the state, apply the transition and persist the result without another writer interleaving. How it achieves that is its own business - a lock in-process, a Lua script in Redis.- abstractmethod check(algorithm, rates, now, weight)¶
Apply
algorithm.stepto the stored state, atomically.
- close()¶
Release any resources held. Optional.
- Return type:
None
- default_clock = <pyrate_limiter.clocks.MonotonicClock object>¶
Used when the bucket is not given a clock. Shared stores override it, since a monotonic clock means nothing across machines.
- is_async = False¶
Nonemeans “ask the Leaker to probe” (a client that may be either).
- abstractmethod read(algorithm, rates)¶
Current state. For reporting only - never the basis of a decision.
- Return type:
Tuple[float,...] |Awaitable[Tuple[float,...]]
- abstractmethod reset()¶
Forget everything, as though the key had never been used.
- Return type:
None|Awaitable[None]
- class pyrate_limiter.abstracts.TokenBucket¶
Bases:
GCRAToken bucket, which is GCRA under a more familiar name.
A bucket of
rate.bursttokens refilling atrate.limit / rate.intervaladmits exactly what GCRA does with an emission interval ofinterval / limit. Same implementation, one float of state rather than a token count plus a refill timestamp.
Submodules¶
- pyrate_limiter.abstracts.algorithm module
- pyrate_limiter.abstracts.bucket module
AbstractBucketAbstractBucket.close()AbstractBucket.count()AbstractBucket.failing_rateAbstractBucket.flush()AbstractBucket.is_asyncAbstractBucket.leak()AbstractBucket.limiter_lock()AbstractBucket.now()AbstractBucket.peek()AbstractBucket.put()AbstractBucket.put_decision()AbstractBucket.ratesAbstractBucket.waiting()
BucketFactoryLeaker
- pyrate_limiter.abstracts.rate module
- pyrate_limiter.abstracts.store module
- pyrate_limiter.abstracts.wrappers module