use std::future::Future;
pub trait Backend: Send + Sync {
fn wait(&self) -> impl Future<Output = ()> + Send;
}
#[derive(Debug, Clone, Default)]
pub struct RateLimit<B = NoRateLimit> {
backend: B,
}
impl<B: Backend> RateLimit<B> {
pub fn new(backend: B) -> Self {
Self { backend }
}
pub async fn wait(&self) {
self.backend.wait().await;
}
}
impl<B: Backend> From<B> for RateLimit<B> {
fn from(backend: B) -> Self {
Self::new(backend)
}
}
#[derive(Debug, Default, Clone, Copy)]
pub struct NoRateLimit;
impl Backend for NoRateLimit {
async fn wait(&self) {}
}
#[cfg(feature = "governor")]
pub use governor::DefaultDirectRateLimiter as Governor;
#[cfg(feature = "governor")]
mod governor_impl {
use governor::middleware::RateLimitingMiddleware;
use governor::state::{DirectStateStore, NotKeyed};
use governor::{NotUntil, Quota, RateLimiter, clock};
use super::{Backend, Governor, RateLimit};
impl<S, C, MW> Backend for RateLimiter<NotKeyed, S, C, MW>
where
S: DirectStateStore + Send + Sync,
C: clock::ReasonablyRealtime + Send + Sync,
C::Instant: Send,
MW: RateLimitingMiddleware<C::Instant, NegativeOutcome = NotUntil<C::Instant>>
+ Send
+ Sync,
MW::PositiveOutcome: Send,
{
async fn wait(&self) {
self.until_ready().await;
}
}
impl RateLimit<Governor> {
pub fn from_quota(quota: Quota) -> Self {
RateLimit::new(Governor::direct(quota))
}
}
}