forcebot_rs/src/core/ratelimiter.rs

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();
}
}