7 changed files with 88 additions and 12 deletions
@ -0,0 +1,67 @@ |
|||||||
|
use std::iter; |
||||||
|
use std::num::NonZeroUsize; |
||||||
|
use std::sync::Mutex; |
||||||
|
use std::time::SystemTime; |
||||||
|
|
||||||
|
use lru::LruCache; |
||||||
|
|
||||||
|
pub struct Limiter { |
||||||
|
record: Mutex<LruCache<i32, Vec<u64>>>, |
||||||
|
amount: u64, |
||||||
|
interval: u64, |
||||||
|
} |
||||||
|
|
||||||
|
impl Limiter { |
||||||
|
pub fn init(amount: u64, interval: u64) -> Self { |
||||||
|
Self { |
||||||
|
record: Mutex::new(LruCache::new(NonZeroUsize::new(2000).unwrap())), |
||||||
|
amount, |
||||||
|
interval, |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
pub fn check(&self, uid: i32) -> bool { |
||||||
|
let t = SystemTime::now() |
||||||
|
.duration_since(SystemTime::UNIX_EPOCH) |
||||||
|
.unwrap() |
||||||
|
.as_secs(); |
||||||
|
let mut r = self.record.lock().unwrap(); |
||||||
|
if let Some(ts) = r.pop(&uid) { |
||||||
|
let new_ts: Vec<u64> = ts |
||||||
|
.into_iter() |
||||||
|
.chain(iter::once(t)) |
||||||
|
.filter(|&tt| tt + self.interval > t) |
||||||
|
.collect(); |
||||||
|
let len = new_ts.len() as u64; |
||||||
|
r.put(uid, new_ts); |
||||||
|
len < self.amount |
||||||
|
} else { |
||||||
|
r.put(uid, vec![t]); |
||||||
|
true |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
pub struct MainLimiters { |
||||||
|
post_min: Limiter, |
||||||
|
post_hour: Limiter, |
||||||
|
get_hour: Limiter, |
||||||
|
} |
||||||
|
|
||||||
|
impl MainLimiters { |
||||||
|
pub fn init() -> Self { |
||||||
|
Self { |
||||||
|
post_min: Limiter::init(6, 60), |
||||||
|
post_hour: Limiter::init(50, 3600), |
||||||
|
get_hour: Limiter::init(1000, 3600), |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
pub fn check(&self, is_post: bool, uid: i32) -> bool { |
||||||
|
if is_post { |
||||||
|
self.post_hour.check(uid) && self.post_min.check(uid) |
||||||
|
} else { |
||||||
|
self.get_hour.check(uid) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue