use std::collections::HashMap;
use std::sync::RwLock;
use super::data::SessionData;
#[derive(Debug, Default)]
pub struct SessionStore {
pub(super) sessions: RwLock<HashMap<String, SessionData>>,
max_sessions_before_cleanup: std::sync::atomic::AtomicUsize,
}
impl SessionStore {
pub const DEFAULT_CLEANUP_THRESHOLD: usize = 10_000;
pub fn new() -> Self {
Self::with_cleanup_threshold(Self::DEFAULT_CLEANUP_THRESHOLD)
}
pub fn with_cleanup_threshold(threshold: usize) -> Self {
Self {
sessions: RwLock::new(HashMap::new()),
max_sessions_before_cleanup: std::sync::atomic::AtomicUsize::new(threshold),
}
}
pub fn set_cleanup_threshold(&self, threshold: usize) {
self.max_sessions_before_cleanup
.store(threshold, std::sync::atomic::Ordering::Relaxed);
}
pub fn get(&self, id: &str) -> Option<SessionData> {
let sessions = self.sessions.read().unwrap_or_else(|e| e.into_inner());
sessions.get(id).cloned()
}
pub fn save(&self, session: SessionData) {
let mut sessions = self.sessions.write().unwrap_or_else(|e| e.into_inner());
let was_at_or_below = sessions.len()
<= self
.max_sessions_before_cleanup
.load(std::sync::atomic::Ordering::Relaxed);
sessions.insert(session.id.clone(), session);
let threshold = self
.max_sessions_before_cleanup
.load(std::sync::atomic::Ordering::Relaxed);
if was_at_or_below && sessions.len() > threshold {
sessions.retain(|_, s| s.is_valid());
}
}
pub fn delete(&self, id: &str) {
let mut sessions = self.sessions.write().unwrap_or_else(|e| e.into_inner());
sessions.remove(id);
}
pub fn cleanup(&self) {
let mut sessions = self.sessions.write().unwrap_or_else(|e| e.into_inner());
sessions.retain(|_, session| session.is_valid());
}
pub fn clear(&self) {
let mut sessions = self.sessions.write().unwrap_or_else(|e| e.into_inner());
sessions.clear();
}
pub fn len(&self) -> usize {
let sessions = self.sessions.read().unwrap_or_else(|e| e.into_inner());
sessions.len()
}
pub fn is_empty(&self) -> bool {
let sessions = self.sessions.read().unwrap_or_else(|e| e.into_inner());
sessions.is_empty()
}
}