tako_rs_plugins/middleware/session/
store.rs1use std::sync::Arc;
5use std::time::Duration;
6use std::time::Instant;
7
8use scc::HashMap as SccHashMap;
9
10#[derive(Clone, Copy)]
12pub struct SessionTtl {
13 pub idle_secs: u64,
15 pub absolute_secs: Option<u64>,
18}
19
20impl Default for SessionTtl {
21 fn default() -> Self {
22 Self {
23 idle_secs: 3_600,
24 absolute_secs: Some(86_400),
25 }
26 }
27}
28
29#[derive(Clone)]
30pub(crate) struct SessionEntry {
31 pub(crate) data: serde_json::Map<String, serde_json::Value>,
32 pub(crate) created_at: Instant,
33 pub(crate) last_seen_at: Instant,
34}
35
36#[derive(Clone)]
38pub(crate) struct Store(Arc<SccHashMap<String, SessionEntry>>);
39
40impl Store {
41 pub(crate) fn new() -> Self {
42 Self(Arc::new(SccHashMap::new()))
43 }
44
45 pub(crate) fn get(&self, id: &str) -> Option<SessionEntry> {
46 self.0.get_sync(id).map(|e| e.clone())
47 }
48
49 pub(crate) fn upsert(&self, id: String, entry: SessionEntry) {
50 let _ = self.0.upsert_sync(id, entry);
51 }
52
53 pub(crate) fn remove(&self, id: &str) {
54 let _ = self.0.remove_sync(id);
55 }
56
57 fn revoke_all(&self) {
58 self.0.clear_sync();
59 }
60
61 fn revoke_predicate(&self, mut keep: impl FnMut(&str, &SessionEntry) -> bool) {
62 self.0.retain_sync(|k, v| keep(k, v));
63 }
64
65 pub(crate) fn retain_expired(&self, ttl: SessionTtl) {
66 let now = Instant::now();
67 let idle = Duration::from_secs(ttl.idle_secs);
68 let absolute = ttl.absolute_secs.map(Duration::from_secs);
69 self.0.retain_sync(|_, v| {
70 if now.duration_since(v.last_seen_at) > idle {
71 return false;
72 }
73 if let Some(abs) = absolute
74 && now.duration_since(v.created_at) > abs
75 {
76 return false;
77 }
78 true
79 });
80 }
81}
82
83#[derive(Clone)]
85pub struct SessionStoreHandle {
86 pub(crate) store: Store,
87}
88
89impl SessionStoreHandle {
90 pub fn revoke_all(&self) {
92 self.store.revoke_all();
93 }
94
95 pub fn revoke_where<F>(&self, mut pred: F)
97 where
98 F: FnMut(&str, &serde_json::Map<String, serde_json::Value>) -> bool,
99 {
100 self.store.revoke_predicate(|k, v| !pred(k, &v.data));
101 }
102}