use dashmap::DashMap;
use crate::invalidation_client::InvalidationSink;
pub struct PolicyL1Cache<V> {
entries: DashMap<String, V>,
}
impl<V> Default for PolicyL1Cache<V> {
fn default() -> Self {
Self {
entries: DashMap::new(),
}
}
}
impl<V> PolicyL1Cache<V> {
pub fn new() -> Self {
Self::default()
}
pub fn insert(&self, agent_id: impl Into<String>, value: V) {
self.entries.insert(agent_id.into(), value);
}
pub fn invalidate(&self, agent_id: &str) {
self.entries.remove(agent_id);
}
pub fn invalidate_all(&self) {
self.entries.clear();
}
pub fn contains(&self, agent_id: &str) -> bool {
self.entries.contains_key(agent_id)
}
pub fn len(&self) -> usize {
self.entries.len()
}
pub fn is_empty(&self) -> bool {
self.entries.is_empty()
}
}
impl<V: Clone> PolicyL1Cache<V> {
pub fn get(&self, agent_id: &str) -> Option<V> {
self.entries.get(agent_id).map(|entry| entry.value().clone())
}
}
impl<V: Send + Sync> InvalidationSink for PolicyL1Cache<V> {
fn on_policy_invalidated(&self, agent_id: &str) {
if agent_id.is_empty() {
self.invalidate_all();
} else {
self.invalidate(agent_id);
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn insert_and_get_roundtrip() {
let cache: PolicyL1Cache<bool> = PolicyL1Cache::new();
cache.insert("agent-a", true);
assert_eq!(cache.get("agent-a"), Some(true));
assert!(cache.contains("agent-a"));
assert_eq!(cache.len(), 1);
}
#[test]
fn invalidate_drops_only_the_named_entry() {
let cache: PolicyL1Cache<u8> = PolicyL1Cache::new();
cache.insert("agent-a", 1);
cache.insert("agent-b", 2);
cache.invalidate("agent-a");
assert!(!cache.contains("agent-a"));
assert_eq!(cache.get("agent-b"), Some(2));
assert_eq!(cache.len(), 1);
}
#[test]
fn sink_named_agent_invalidates_one() {
let cache: PolicyL1Cache<u8> = PolicyL1Cache::new();
cache.insert("agent-a", 1);
cache.insert("agent-b", 2);
cache.on_policy_invalidated("agent-a");
assert!(!cache.contains("agent-a"));
assert!(cache.contains("agent-b"));
}
#[test]
fn sink_empty_agent_invalidates_all() {
let cache: PolicyL1Cache<u8> = PolicyL1Cache::new();
cache.insert("agent-a", 1);
cache.insert("agent-b", 2);
cache.on_policy_invalidated("");
assert!(cache.is_empty());
}
}