80 lines
1.9 KiB
Rust
80 lines
1.9 KiB
Rust
const TIME_THRESHOLD_S: u64 = 30;
|
|
const TIME_MIN_S_F64: f64 = 1.0;
|
|
const MSG_THRESHOLD: u32 = 20;
|
|
|
|
use std::time::Instant;
|
|
use crate::core::botlog;
|
|
|
|
#[derive(Debug, Clone)]
|
|
pub struct RateLimiter {
|
|
timer: Instant,
|
|
msgcounter: u32,
|
|
lastmsgtimer : Instant,
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub enum LimiterResp {
|
|
Allow, // when it's evaluated to be within limits
|
|
Skip, // as outside of rate limits
|
|
// Enqueue, // [FUTURE]
|
|
Sleep(f64), // Sleep for x seconds
|
|
}
|
|
|
|
impl Default for RateLimiter {
|
|
fn default() -> Self {
|
|
Self::new()
|
|
}
|
|
}
|
|
|
|
impl RateLimiter {
|
|
pub fn new() -> Self {
|
|
Self {
|
|
timer: Instant::now(),
|
|
msgcounter: 0,
|
|
lastmsgtimer: Instant::now(),
|
|
}
|
|
}
|
|
|
|
pub fn check_limiter(&mut self) -> LimiterResp {
|
|
|
|
|
|
let logstr = format!(
|
|
">> RateLimiter > {:?}",self
|
|
);
|
|
|
|
botlog::trace(
|
|
logstr.as_str(),
|
|
Some("Rate Limiter Inner".to_string()),
|
|
None,
|
|
);
|
|
|
|
|
|
let rsp = if self.timer.elapsed().as_secs() >= TIME_THRESHOLD_S {
|
|
self.timer = Instant::now();
|
|
self.msgcounter = 0;
|
|
LimiterResp::Allow
|
|
} else if self.msgcounter < MSG_THRESHOLD &&
|
|
self.lastmsgtimer.elapsed().as_secs_f64() >= TIME_MIN_S_F64 {
|
|
LimiterResp::Allow
|
|
} else {
|
|
// when elapsed() < TIME_THRESHOLD_S && msgcounter >= MSG_THRESHOLD
|
|
// LimiterResp::Skip
|
|
LimiterResp::Sleep(TIME_MIN_S_F64 - self.lastmsgtimer.elapsed().as_secs_f64() + 0.1)
|
|
};
|
|
|
|
botlog::trace(
|
|
&format!("Limiter Response : {:?} ; Elapsed (as_sec_f64) : {}",
|
|
rsp, self.lastmsgtimer.elapsed().as_secs_f64()),
|
|
Some("Rate Limiter Inner".to_string()),
|
|
None,
|
|
);
|
|
|
|
rsp
|
|
|
|
}
|
|
|
|
pub fn increment_counter(&mut self) {
|
|
self.msgcounter += 1;
|
|
self.lastmsgtimer = Instant::now();
|
|
}
|
|
}
|