use async_trait::async_trait;
use crate::Result;
#[derive(Debug, Clone)]
pub struct QuotaConfig {
pub max_messages: Option<usize>,
pub max_bytes: Option<usize>,
pub max_rate_per_sec: Option<f64>,
pub max_messages_per_consumer: Option<usize>,
pub enforcement: QuotaEnforcement,
}
impl QuotaConfig {
pub fn new() -> Self {
Self {
max_messages: None,
max_bytes: None,
max_rate_per_sec: None,
max_messages_per_consumer: None,
enforcement: QuotaEnforcement::Reject,
}
}
pub fn with_max_messages(mut self, max: usize) -> Self {
self.max_messages = Some(max);
self
}
pub fn with_max_bytes(mut self, max: usize) -> Self {
self.max_bytes = Some(max);
self
}
pub fn with_max_rate(mut self, rate: f64) -> Self {
self.max_rate_per_sec = Some(rate);
self
}
pub fn with_max_per_consumer(mut self, max: usize) -> Self {
self.max_messages_per_consumer = Some(max);
self
}
pub fn with_enforcement(mut self, enforcement: QuotaEnforcement) -> Self {
self.enforcement = enforcement;
self
}
}
impl Default for QuotaConfig {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum QuotaEnforcement {
Reject,
Throttle,
Warn,
}
#[derive(Debug, Clone, Default)]
pub struct QuotaUsage {
pub message_count: usize,
pub bytes_used: usize,
pub current_rate: f64,
pub exceeded: bool,
}
impl QuotaUsage {
pub fn is_message_quota_exceeded(&self, config: &QuotaConfig) -> bool {
if let Some(max) = config.max_messages {
return self.message_count >= max;
}
false
}
pub fn is_bytes_quota_exceeded(&self, config: &QuotaConfig) -> bool {
if let Some(max) = config.max_bytes {
return self.bytes_used >= max;
}
false
}
pub fn is_rate_quota_exceeded(&self, config: &QuotaConfig) -> bool {
if let Some(max) = config.max_rate_per_sec {
return self.current_rate >= max;
}
false
}
pub fn usage_percent(&self, config: &QuotaConfig) -> Option<f64> {
config.max_messages.map(|max| {
if max == 0 {
100.0
} else {
(self.message_count as f64 / max as f64) * 100.0
}
})
}
}
#[async_trait]
pub trait QuotaManager: Send + Sync {
async fn set_quota(&mut self, queue: &str, config: QuotaConfig) -> Result<()>;
async fn get_quota(&mut self, queue: &str) -> Result<QuotaConfig>;
async fn quota_usage(&mut self, queue: &str) -> Result<QuotaUsage>;
async fn reset_quota(&mut self, queue: &str) -> Result<()>;
async fn check_quota(&mut self, queue: &str, message_size: usize) -> Result<bool>;
}