use std::time::Duration;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Quota {
pub(crate) emission_interval_nanos: u64,
pub(crate) burst_tolerance_nanos: u64,
pub(crate) max_burst: u32,
}
impl Quota {
pub fn with_period(requests: u32, period: Duration) -> Self {
let reqs = requests.max(1);
let period_nanos = period.as_nanos().max(1) as u64;
let emission_interval_nanos = (period_nanos / reqs as u64).max(1);
let max_burst = reqs;
let burst_tolerance_nanos = emission_interval_nanos.saturating_mul(max_burst as u64);
Self {
emission_interval_nanos,
burst_tolerance_nanos,
max_burst,
}
}
pub fn per_second(requests: u32) -> Self {
Self::with_period(requests, Duration::from_secs(1))
}
pub fn per_minute(requests: u32) -> Self {
Self::with_period(requests, Duration::from_secs(60))
}
pub fn per_hour(requests: u32) -> Self {
Self::with_period(requests, Duration::from_secs(3600))
}
#[must_use]
pub fn allow_burst(mut self, burst: u32) -> Self {
let b = burst.max(1);
self.max_burst = b;
self.burst_tolerance_nanos = self.emission_interval_nanos.saturating_mul(b as u64);
self
}
#[inline]
pub fn emission_interval(&self) -> Duration {
Duration::from_nanos(self.emission_interval_nanos)
}
#[inline]
pub fn max_burst(&self) -> u32 {
self.max_burst
}
}