#[cfg(feature = "gcra")]
mod gcra;
#[cfg(feature = "leaky-bucket")]
mod leaky_bucket;
#[cfg(feature = "sliding-log")]
mod sliding_log;
#[cfg(feature = "concurrent")]
mod concurrent;
mod fixed_window;
mod sliding_window;
mod token_bucket;
#[cfg(feature = "gcra")]
pub use gcra::GCRA;
#[cfg(feature = "leaky-bucket")]
pub use leaky_bucket::LeakyBucket;
#[cfg(feature = "sliding-log")]
pub use sliding_log::SlidingLog;
#[cfg(feature = "concurrent")]
pub use concurrent::ConcurrentLimiter;
pub use fixed_window::FixedWindow;
pub use sliding_window::SlidingWindow;
pub use token_bucket::TokenBucket;
use std::future::Future;
use crate::decision::Decision;
use crate::error::Result;
use crate::quota::Quota;
use crate::storage::Storage;
pub trait Algorithm: Send + Sync + 'static {
fn name(&self) -> &'static str;
fn check_and_record<S: Storage>(
&self,
storage: &S,
key: &str,
quota: &Quota,
) -> impl Future<Output = Result<Decision>> + Send;
fn check<S: Storage>(
&self,
storage: &S,
key: &str,
quota: &Quota,
) -> impl Future<Output = Result<Decision>> + Send;
fn reset<S: Storage>(&self, storage: &S, key: &str) -> impl Future<Output = Result<()>> + Send {
async move { storage.delete(key).await }
}
}
pub(crate) fn current_timestamp_ms() -> u64 {
use std::time::{SystemTime, UNIX_EPOCH};
SystemTime::now()
.duration_since(UNIX_EPOCH)
.expect("Time went backwards")
.as_millis() as u64
}
pub(crate) fn timestamp_to_instant(timestamp_ms: u64) -> std::time::Instant {
let now = std::time::Instant::now();
let now_ms = current_timestamp_ms();
if timestamp_ms >= now_ms {
now + std::time::Duration::from_millis(timestamp_ms - now_ms)
} else {
now - std::time::Duration::from_millis(now_ms - timestamp_ms)
}
}