pub struct SlidingWindowRateLimiter { /* private fields */ }
Expand description
A rate limiter that records calls (optionally with a specified cost) during a sliding window Duration
.
SlidingWindowRateLimiter
implements both [RateLimiter
] and [VariableCostRateLimiter
], so both
SlidingWindowRateLimiter::wait_until_ready()
and SlidingWindowRateLimiter::wait_with_cost()
can be used (even together). For instance, limiter.wait_until_ready().await
and limiter.wait_with_cost(1).await
would have the same effect.
§Example: Simple Rate Limiter
A method that calls an external API with a rate limit should not be called more than three times per second.
use tokio::time::{Instant, Duration};
use async_rate_limit::limiters::RateLimiter;
use async_rate_limit::sliding_window::SlidingWindowRateLimiter;
#[tokio::main]
async fn main() -> () {
let mut limiter = SlidingWindowRateLimiter::new(Duration::from_secs(1), 3);
for _ in 0..4 {
// the 4th call will take place ~1 second after the first call
limited_method(&mut limiter).await;
}
}
// note the use of the `RateLimiter` trait, rather than the direct type
async fn limited_method<T>(limiter: &mut T) where T: RateLimiter {
limiter.wait_until_ready().await;
println!("{:?}", Instant::now());
}
Implementations§
Source§impl SlidingWindowRateLimiter
impl SlidingWindowRateLimiter
Sourcepub fn new(window: Duration, limit: usize) -> Self
pub fn new(window: Duration, limit: usize) -> Self
Creates a new SlidingWindowRateLimiter
that allows limit
calls during any window
Duration.
Sourcepub fn new_with_permits(window: Duration, permits: Arc<Semaphore>) -> Self
pub fn new_with_permits(window: Duration, permits: Arc<Semaphore>) -> Self
Creates a new SlidingWindowRateLimiter
with an externally provided Arc<Semaphore>
for permits.
§Example: A Shared Variable Cost Rate Limiter
use std::sync::Arc;
use tokio::sync::Semaphore;
use async_rate_limit::limiters::VariableCostRateLimiter;
use async_rate_limit::sliding_window::SlidingWindowRateLimiter;
use tokio::time::{Instant, Duration};
#[tokio::main]
async fn main() -> () {
let permits = Arc::new(Semaphore::new(5));
let mut limiter1 =
SlidingWindowRateLimiter::new_with_permits(Duration::from_secs(2), permits.clone());
let mut limiter2 =
SlidingWindowRateLimiter::new_with_permits(Duration::from_secs(2), permits.clone());
// Note: the above is semantically equivalent to creating `limiter1` with
// `SlidingWindowRateLimiter::new`, then cloning it.
limiter1.wait_with_cost(3).await;
// the second call will wait 2s, since the first call consumed 3/5 shared permits
limiter2.wait_with_cost(3).await;
}
Trait Implementations§
Source§impl Clone for SlidingWindowRateLimiter
impl Clone for SlidingWindowRateLimiter
Source§fn clone(&self) -> SlidingWindowRateLimiter
fn clone(&self) -> SlidingWindowRateLimiter
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source
. Read moreSource§impl Debug for SlidingWindowRateLimiter
impl Debug for SlidingWindowRateLimiter
Source§impl ThreadsafeRateLimiter for SlidingWindowRateLimiter
impl ThreadsafeRateLimiter for SlidingWindowRateLimiter
Source§async fn wait_until_ready(&self)
async fn wait_until_ready(&self)
Wait with an implied cost of 1, see the initial example
Source§impl ThreadsafeVariableRateLimiter for SlidingWindowRateLimiter
impl ThreadsafeVariableRateLimiter for SlidingWindowRateLimiter
Source§async fn wait_with_cost(&self, cost: usize)
async fn wait_with_cost(&self, cost: usize)
Wait with some variable cost per usage.
§Example: A Shared Variable Cost Rate Limiter
An API specifies that you may make 5 “calls” per second, but some endpoints cost more than one call.
/lite
costs 1 unit per call/heavy
costs 3 units per call
use tokio::time::{Instant, Duration};
use async_rate_limit::limiters::VariableCostRateLimiter;
use async_rate_limit::sliding_window::SlidingWindowRateLimiter;
#[tokio::main]
async fn main() -> () {
let mut limiter = SlidingWindowRateLimiter::new(Duration::from_secs(1), 5);
for _ in 0..3 {
// these will proceed immediately, spending 3 units
get_lite(&mut limiter).await;
}
// 3/5 units are spent, so this will wait for ~1s to proceed since it costs another 3
get_heavy(&mut limiter).await;
}
// note the use of the `VariableCostRateLimiter` trait, rather than the direct type
async fn get_lite<T>(limiter: &mut T) where T: VariableCostRateLimiter {
limiter.wait_with_cost(1).await;
println!("Lite: {:?}", Instant::now());
}
async fn get_heavy<T>(limiter: &mut T) where T: VariableCostRateLimiter {
limiter.wait_with_cost(3).await;
println!("Heavy: {:?}", Instant::now());
}
Auto Trait Implementations§
impl Freeze for SlidingWindowRateLimiter
impl !RefUnwindSafe for SlidingWindowRateLimiter
impl Send for SlidingWindowRateLimiter
impl Sync for SlidingWindowRateLimiter
impl Unpin for SlidingWindowRateLimiter
impl !UnwindSafe for SlidingWindowRateLimiter
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§unsafe fn clone_to_uninit(&self, dst: *mut T)
unsafe fn clone_to_uninit(&self, dst: *mut T)
clone_to_uninit
)