use dashmap::DashMap;
use crate::gcra::check_gcra;
use crate::quota::{Nanos, Quota};
use crate::storage::{Storage, StorageFuture};
pub struct MemoryStorage {
state: DashMap<String, Nanos>,
}
impl MemoryStorage {
pub fn new() -> Self {
Self {
state: DashMap::new(),
}
}
pub fn len(&self) -> usize {
self.state.len()
}
pub fn is_empty(&self) -> bool {
self.state.is_empty()
}
pub fn retain_active(&self, now: Nanos) {
self.state.retain(|_, tat| *tat >= now);
}
}
impl Default for MemoryStorage {
fn default() -> Self {
Self::new()
}
}
impl Storage for MemoryStorage {
fn check_and_update(
&self,
key: &str,
quota: &Quota,
cost: u32,
now: Nanos,
) -> StorageFuture<'_> {
let ei = quota.emission_interval_nanos();
let bo = quota.burst_offset_nanos();
let current_tat = self.state.get(key).map(|e| *e.value());
let result = match check_gcra(current_tat, now, ei, bo, cost) {
Ok((new_tat, info)) => {
self.state.insert(key.to_owned(), new_tat);
Ok(Ok(info))
}
Err(limited) => Ok(Err(limited)),
};
Box::pin(std::future::ready(result))
}
}