use std::time::{Duration, Instant};
use dashmap::DashMap;
use super::failure::DenyReason;
#[derive(Clone)]
pub(super) enum CachedOutcome {
Resolved(serde_json::Map<String, serde_json::Value>),
Denied(DenyReason),
}
struct CacheEntry {
outcome: CachedOutcome,
sub: String,
expires_at: Instant,
}
#[derive(Default)]
pub(super) struct IdentityCache {
entries: DashMap<String, CacheEntry>,
}
impl IdentityCache {
pub(super) fn new() -> Self {
Self::default()
}
pub(super) fn get(&self, key: &str) -> Option<CachedOutcome> {
let entry = self.entries.get(key)?;
if Instant::now() < entry.expires_at {
Some(entry.outcome.clone())
} else {
drop(entry);
self.entries.remove(key);
None
}
}
pub(super) fn insert(&self, key: String, sub: String, outcome: CachedOutcome, ttl: Duration) {
self.entries.insert(
key,
CacheEntry {
outcome,
sub,
expires_at: Instant::now() + ttl,
},
);
}
pub(super) fn flush(&self, sub: &str) {
self.entries.retain(|_key, entry| entry.sub != sub);
}
pub(super) fn flush_all(&self) {
self.entries.clear();
}
#[cfg(test)]
pub(super) fn len(&self) -> usize {
self.entries.len()
}
}