use std::time::{Duration, Instant};
use dashmap::DashMap;
use crate::limiter::CacheBackend;
#[derive(Debug)]
struct CacheEntry {
value: u32,
expires_at: Instant,
}
pub struct InMemoryCache {
store: DashMap<String, CacheEntry>,
}
impl InMemoryCache {
pub fn new() -> Self {
InMemoryCache {
store: DashMap::new(),
}
}
}
impl CacheBackend for InMemoryCache {
fn get(&self, key: &str) -> Option<u32> {
if let Some(entry) = self.store.get(key) {
if entry.expires_at > Instant::now() {
return Some(entry.value);
} else {
drop(entry);
self.store.remove(key);
return None;
}
} else {
return None;
}
}
fn set(&self, key: &str, value: u32, ttl: Duration) -> Result<(), String> {
let expires_at = Instant::now() + ttl;
let entry = CacheEntry { value, expires_at };
self.store.insert(key.to_string(), entry);
Ok(())
}
fn incr(&self, key: &str, amount: u32) -> Result<u32, String> {
let now = Instant::now();
if let Some(mut entry) = self.store.get_mut(key) {
if entry.expires_at <= now {
entry.value = amount;
} else {
entry.value += amount;
}
Ok(entry.value)
} else {
self.store.insert(key.to_string(), CacheEntry {
value: amount,
expires_at: now, });
Ok(amount)
}
}
}