Skip to main content

RateLimiter

Struct RateLimiter 

Source
pub struct RateLimiter { /* private fields */ }
Expand description

Per-user token buckets, one per (user, Class).

§Algorithm

A classic token bucket, refilled continuously rather than on a timer: capacity is one minute’s allowance, tokens accrue at per_minute / 60 per second, and each admitted request spends one. A bucket is refilled lazily when it is read, so there is no background thread and no periodic sweep — which is what lets this stay synchronous, allocation-light, and free on an idle node.

Capacity equal to a full minute means an agent may burst a minute’s worth at once and then proceeds at the sustained rate, which is the shape real agent traffic has: a batch of work, then a wait.

§Bounds

The map holds one entry per (authenticated user, class) that has been seen. Usernames come from the operator’s --auth-file, and the caller only consults the limiter for authenticated users, so the map is bounded by the credential count times two and cannot be grown by an unauthenticated caller.

Implementations§

Source§

impl RateLimiter

Source

pub fn new( api_per_minute: Option<NonZeroU32>, git_per_minute: Option<NonZeroU32>, ) -> Self

A limiter with the given requests-per-minute ceilings. None for a class means that class is not limited.

The ceilings are NonZeroU32 so that “limit to zero” — a value that refuses every request forever and has no sensible Retry-After — is not representable.

Source

pub fn is_active(&self) -> bool

Whether any class is limited at all.

Source

pub fn check(&self, user: &str, class: Class) -> Option<u64>

Spends one token for user in class.

None admits the request. Some(seconds) refuses it and is the Retry-After the caller should answer with: the whole seconds until one token has accrued, never less than one.

Source

pub fn check_at(&self, user: &str, class: Class, now: Instant) -> Option<u64>

RateLimiter::check against a caller-supplied clock reading, so refill can be proved without sleeping through it.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.