confium_coordinator/coordinator/
session_timeout.rs1use chrono::{DateTime, Duration, Utc};
4use serde::{Deserialize, Serialize};
5use std::collections::HashMap;
6use std::sync::Mutex;
7
8#[derive(Debug, Clone, Serialize, Deserialize)]
10pub struct SessionDeadline {
11 pub session_id: String,
12 pub deadline: DateTime<Utc>,
13}
14
15#[derive(Default)]
17pub struct SessionTimeoutManager {
18 deadlines: Mutex<HashMap<String, DateTime<Utc>>>,
19}
20
21impl SessionTimeoutManager {
22 pub fn new() -> Self {
23 Self::default()
24 }
25
26 pub fn set_deadline(&self, session_id: &str, timeout: Duration) {
28 let deadline = Utc::now() + timeout;
29 self.deadlines
30 .lock()
31 .unwrap()
32 .insert(session_id.into(), deadline);
33 }
34
35 pub fn clear(&self, session_id: &str) {
37 self.deadlines.lock().unwrap().remove(session_id);
38 }
39
40 pub fn expired_sessions(&self) -> Vec<SessionDeadline> {
42 let now = Utc::now();
43 self.deadlines
44 .lock()
45 .unwrap()
46 .iter()
47 .filter(|(_, deadline)| **deadline < now)
48 .map(|(sid, deadline)| SessionDeadline {
49 session_id: sid.clone(),
50 deadline: *deadline,
51 })
52 .collect()
53 }
54
55 pub fn count(&self) -> usize {
57 self.deadlines.lock().unwrap().len()
58 }
59
60 pub fn is_expired(&self, session_id: &str) -> bool {
62 let now = Utc::now();
63 self.deadlines
64 .lock()
65 .unwrap()
66 .get(session_id)
67 .map(|d| *d < now)
68 .unwrap_or(false)
69 }
70}
71
72#[cfg(test)]
73mod tests {
74 use super::*;
75
76 #[test]
77 fn set_and_check_not_expired() {
78 let mgr = SessionTimeoutManager::new();
79 mgr.set_deadline("s1", Duration::minutes(5));
80 assert!(!mgr.is_expired("s1"));
81 }
82
83 #[test]
84 fn expired_after_deadline() {
85 let mgr = SessionTimeoutManager::new();
86 mgr.set_deadline("s1", Duration::seconds(-1)); assert!(mgr.is_expired("s1"));
88 }
89
90 #[test]
91 fn clear_removes_deadline() {
92 let mgr = SessionTimeoutManager::new();
93 mgr.set_deadline("s1", Duration::minutes(5));
94 mgr.clear("s1");
95 assert!(!mgr.is_expired("s1"));
96 assert_eq!(mgr.count(), 0);
97 }
98
99 #[test]
100 fn expired_sessions_returns_list() {
101 let mgr = SessionTimeoutManager::new();
102 mgr.set_deadline("s1", Duration::minutes(5));
103 mgr.set_deadline("s2", Duration::seconds(-1));
104 mgr.set_deadline("s3", Duration::seconds(-1));
105 let expired = mgr.expired_sessions();
106 assert_eq!(expired.len(), 2);
107 }
108
109 #[test]
110 fn count_tracks_sessions() {
111 let mgr = SessionTimeoutManager::new();
112 assert_eq!(mgr.count(), 0);
113 mgr.set_deadline("s1", Duration::minutes(5));
114 mgr.set_deadline("s2", Duration::minutes(5));
115 assert_eq!(mgr.count(), 2);
116 }
117
118 #[test]
119 fn unknown_session_not_expired() {
120 let mgr = SessionTimeoutManager::new();
121 assert!(!mgr.is_expired("unknown"));
122 }
123}