use std::ops::Deref;
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering};
use tokio::time::{interval, Duration};
use crate::core::session_wrappers::{Session, SessionMap};
pub struct SessionsManager {
session_map: Arc<SessionMap>,
cancel_token: Arc<AtomicBool>,
cleanup_interval: Option<u64>,
}
impl Deref for SessionsManager {
type Target = Arc<SessionMap>;
fn deref(&self) -> &Self::Target {
&self.session_map
}
}
impl SessionsManager {
pub fn new(sessions_option: Option<Vec<Session>>, valid_session_duration: Option<i64>, cleanup_interval: Option<u64>) -> Self {
let manager = Self {
session_map: Arc::new(
match sessions_option {
None => SessionMap::new(valid_session_duration),
Some(sessions) => SessionMap::from_sessions(sessions, valid_session_duration),
}
),
cancel_token: Arc::new(AtomicBool::new(true)),
cleanup_interval,
};
if let Some(interval) = manager.cleanup_interval.clone() {
manager.start_cleanup(interval);
}
manager
}
pub fn cleanup_interval(&self) -> Option<u64> {
self.cleanup_interval
}
pub(super) fn start_cleanup(&self, cleanup_interval: u64) {
if self.cancel_token.load(Ordering::Acquire) {
self.cancel_token.store(false, Ordering::Release);
let cancel_token = self.cancel_token.clone();
let sessions_map = self.session_map.clone();
tokio::spawn(async move {
let mut cleanup_interval = interval(Duration::from_secs(cleanup_interval));
cleanup_interval.tick().await;
loop {
cleanup_interval.tick().await;
if cancel_token.load(Ordering::Acquire) {
break;
}
sessions_map.delete_invalid_sessions().await;
}
});
}
}
pub(super) fn stop_cleanup(&self) {
if !self.cancel_token.load(Ordering::Acquire) {
self.cancel_token.store(true, Ordering::Release);
}
}
}
impl Drop for SessionsManager {
fn drop(&mut self) {
self.stop_cleanup();
}
}