use std::future::Future;
use std::pin::Pin;
use crate::function::{AuthContext, RequestMetadata};
use crate::rate_limit::{RateLimitConfig, RateLimitKey, RateLimitResult};
use crate::{ForgeError, Result};
pub trait RateLimiterBackend: Send + Sync + 'static {
fn check<'a>(
&'a self,
bucket_key: &'a str,
config: &'a RateLimitConfig,
) -> Pin<Box<dyn Future<Output = Result<RateLimitResult>> + Send + 'a>>;
fn build_key(
&self,
key_type: RateLimitKey,
action_name: &str,
auth: &AuthContext,
request: &RequestMetadata,
) -> String;
fn enforce<'a>(
&'a self,
bucket_key: &'a str,
config: &'a RateLimitConfig,
) -> Pin<Box<dyn Future<Output = Result<RateLimitResult>> + Send + 'a>> {
Box::pin(async move {
let result = self.check(bucket_key, config).await?;
if !result.allowed {
return Err(ForgeError::RateLimitExceeded {
retry_after: result
.retry_after
.unwrap_or(std::time::Duration::from_secs(1)),
limit: config.requests,
remaining: result.remaining,
});
}
Ok(result)
})
}
}