use std::collections::HashMap;
use std::sync::Arc;
use std::time::Instant;
use tokio::sync::RwLock;
#[derive(Clone)]
pub struct VoiceSessionTracker {
inner: Arc<RwLock<HashMap<String, VoiceSession>>>,
timeout_secs: u64,
}
struct VoiceSession {
call_sid: String,
last_activity: Instant,
}
impl VoiceSessionTracker {
pub fn new(timeout_secs: u64) -> Self {
Self {
inner: Arc::new(RwLock::new(HashMap::new())),
timeout_secs,
}
}
pub async fn touch(&self, sender: &str, call_sid: &str) {
let mut sessions = self.inner.write().await;
let entry = sessions
.entry(sender.to_string())
.or_insert_with(|| VoiceSession {
call_sid: call_sid.to_string(),
last_activity: Instant::now(),
});
entry.call_sid = call_sid.to_string();
entry.last_activity = Instant::now();
}
pub async fn remove(&self, call_sid: &str) {
let mut sessions = self.inner.write().await;
sessions.retain(|_, v| v.call_sid != *call_sid);
}
pub async fn active_call_sid(&self, sender: &str) -> Option<String> {
let sessions = self.inner.read().await;
sessions.get(sender).and_then(|s| {
if s.last_activity.elapsed().as_secs() < self.timeout_secs {
Some(s.call_sid.clone())
} else {
None
}
})
}
}