pub struct RateBudget { /* private fields */ }Expand description
A cloneable, thread-safe token bucket. Cheap to clone (bumps an
Arc); the inner state is shared, which is the whole point.
Implementations§
Source§impl RateBudget
impl RateBudget
Sourcepub fn default_system() -> Self
pub fn default_system() -> Self
Build a bucket with the default capacity + refill. Clock
is SystemClock (the only right answer in production).
Sourcepub fn with_clock(
capacity: u32,
refill_per_second: f64,
clock: Arc<dyn Clock>,
) -> Self
pub fn with_clock( capacity: u32, refill_per_second: f64, clock: Arc<dyn Clock>, ) -> Self
Build a bucket with explicit capacity, refill rate, and
clock. Panics if capacity == 0 (a zero-capacity bucket
is never usable and always exhausts; callers intending
“infinitely permissive” should not wire the bucket in at
all) or refill_per_second < 0.0 (a negative refill is
incoherent). A refill of 0.0 is permitted — useful in tests
that want to prove the exhaustion path without accrual
confounding the observation.
§Panics
If capacity == 0 or refill_per_second.is_sign_negative()
or refill_per_second.is_nan(). All three are programmer
errors caught at construction rather than surfaced as
silent “never allows anything” behavior downstream.
Sourcepub fn try_consume(&self, cost: u32) -> Result<(), Exhausted>
pub fn try_consume(&self, cost: u32) -> Result<(), Exhausted>
Attempt to consume cost tokens. Returns Ok(()) on
success (the bucket has been debited), or Err(Exhausted)
with a floor-rounded retry_after when the bucket cannot
satisfy the cost.
A cost that exceeds capacity can never be satisfied —
the caller gets an Exhausted { retry_after } shaped as
“forever-ish” (Duration::MAX). This is a misconfiguration
signal, not a transient error; the caller should surface it
loudly. In practice the cost table’s highest value (3) is
well below the default capacity (60), so this path is a
developer-error canary, not a production concern.
Sourcepub fn refund(&self, cost: u32)
pub fn refund(&self, cost: u32)
Refund cost tokens — used when an outer rate limiter
(the engine’s own 429) fires after we already debited our
local bucket. Without this, every 429 would double-charge
the operator: once against our bucket, once against the
engine’s. Capped at capacity so a runaway refund bug
cannot inflate the bucket beyond its design size.
Sourcepub fn snapshot(&self) -> BudgetSnapshot
pub fn snapshot(&self) -> BudgetSnapshot
Snapshot for display. Runs the refill pass so the returned
token count reflects elapsed time, not the last try_consume
ago — a status bar that reads rate:40/60 when the real
answer is rate:55/60 paints a fake scarcity.
Sourcepub fn reset_to_full(&self)
pub fn reset_to_full(&self)
Force the bucket full. Only wired through
zero doctor --fix (M2_PLAN §1’s clear-counter action) —
operator confirmation is required before this runs, because
bypassing the local bucket has no production use case. The
name is loud on purpose.
Trait Implementations§
Source§impl Clone for RateBudget
impl Clone for RateBudget
Source§fn clone(&self) -> RateBudget
fn clone(&self) -> RateBudget
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more