Skip to main content

Layered

Struct Layered 

Source
pub struct Layered<K, E = K>
where K: Eq + Hash + Clone + Send + Sync + 'static, E: Eq + Hash + Clone + Send + Sync + 'static,
{ /* private fields */ }
Available on crate feature std only.
Expand description

Several scopes of limiting stacked so a request must clear every one.

A real service limits at more than one granularity at once: an overall ceiling for the whole process (the global scope), a fair share per caller (the per-key scope, keyed by tenant or token), and a ceiling per route (the per-endpoint scope). Layered checks the scopes that are configured and admits a request only when all of them can afford it — applied atomically by the same peek-then-commit rule the other composites use, so a request never spends in one scope when another blocks it.

The two key types are independent: a numeric tenant id and a string endpoint, say. They default to the same type for the common all-string case.

Build one with Layered::builder. Every scope is optional; a builder with none admits everything.

§Examples

use throttle_net::{Layered, PerKey, Throttle};

// 1000/s overall, 100/s per tenant, 50/s per endpoint.
let layered = Layered::<String>::builder()
    .global(Throttle::per_second(1000))
    .per_key(PerKey::per_second(100))
    .per_endpoint(PerKey::per_second(50))
    .build();

layered
    .acquire(&"tenant:42".to_string(), &"/v1/chat".to_string())
    .await?;

Implementations§

Source§

impl<K, E> Layered<K, E>
where K: Eq + Hash + Clone + Send + Sync + 'static, E: Eq + Hash + Clone + Send + Sync + 'static,

Source

pub fn builder() -> LayeredBuilder<K, E>

Starts building a layered limiter.

Source

pub fn capacity(&self) -> u32

The binding capacity across configured scopes: the smallest, since that is the first ceiling a request hits. No scopes means unbounded (u32::MAX).

Source

pub fn try_acquire(&self, key: &K, endpoint: &E) -> bool

Attempts to admit one request for (key, endpoint) without waiting.

§Examples
use throttle_net::{Layered, PerKey, Throttle};

let layered = Layered::<&str>::builder()
    .global(Throttle::per_second(2))
    .per_key(PerKey::per_second(1))
    .build();

assert!(layered.try_acquire(&"a", &"/x"));
// The per-key scope for "a" is now empty, even though the global has room.
assert!(!layered.try_acquire(&"a", &"/x"));
assert!(layered.try_acquire(&"b", &"/x")); // a different key is independent
Source

pub fn try_acquire_with_cost(&self, key: &K, endpoint: &E, cost: u32) -> bool

Attempts to admit a request of weight cost for (key, endpoint) without waiting.

Source

pub fn peek(&self, key: &K, endpoint: &E, cost: u32) -> Decision

Reports whether a request for (key, endpoint) would be admitted now, without taking anything.

Source§

impl<K, E> Layered<K, E>
where K: Eq + Hash + Clone + Send + Sync + 'static, E: Eq + Hash + Clone + Send + Sync + 'static,

Source

pub async fn acquire(&self, key: &K, endpoint: &E) -> Result<(), ThrottleError>

Available on crate feature runtime only.

Admits one request for (key, endpoint), waiting until every scope can.

§Errors

Returns ThrottleError::CostExceedsCapacity if some scope’s capacity is too small to ever admit the request.

Source

pub async fn acquire_with_cost( &self, key: &K, endpoint: &E, cost: u32, ) -> Result<(), ThrottleError>

Available on crate feature runtime only.

Admits a request of weight cost for (key, endpoint), waiting until every scope can.

§Errors

Returns ThrottleError::CostExceedsCapacity if some scope can never admit cost.

Auto Trait Implementations§

§

impl<K, E = K> !RefUnwindSafe for Layered<K, E>

§

impl<K, E = K> !UnwindSafe for Layered<K, E>

§

impl<K, E> Freeze for Layered<K, E>

§

impl<K, E> Send for Layered<K, E>

§

impl<K, E> Sync for Layered<K, E>

§

impl<K, E> Unpin for Layered<K, E>

§

impl<K, E> UnsafeUnpin for Layered<K, E>

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<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
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> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

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.
Source§

impl<E> WithErrorCode<E> for E

Source§

fn with_code(self, code: impl Into<String>) -> CodedError<E>

Attach an error code to an error
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more