pub mod memory;
#[cfg(feature = "redis")]
pub mod redis;
use std::fmt;
use std::future::Future;
use std::pin::Pin;
use crate::gcra::{RateLimitInfo, RateLimited};
use crate::quota::{Nanos, Quota};
pub type StorageFuture<'a> = Pin<
Box<dyn Future<Output = Result<Result<RateLimitInfo, RateLimited>, StorageError>> + Send + 'a>,
>;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct StorageKey<'a> {
pub user_id: &'a str,
pub tier: &'a str,
}
impl<'a> StorageKey<'a> {
pub fn new(user_id: &'a str, tier: &'a str) -> Self {
Self { user_id, tier }
}
}
#[derive(Debug)]
pub struct StorageError(pub Box<dyn std::error::Error + Send + Sync>);
impl fmt::Display for StorageError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "storage error: {}", self.0)
}
}
impl std::error::Error for StorageError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
Some(self.0.as_ref())
}
}
pub trait Storage: Send + Sync + 'static {
fn check_and_update<'a>(
&'a self,
key: StorageKey<'a>,
quota: &'a Quota,
cost: u32,
now: Nanos,
) -> StorageFuture<'a>;
}