Skip to main content

rust_mcp_extra/token_verifier/
jwt_cache.rs

1use std::collections::{HashMap, VecDeque};
2use std::time::{Duration, Instant};
3
4/// JWT introspection cache with TTL and max capacity
5pub struct JwtCache {
6    map: HashMap<String, Instant>, // Key -> last introspection time
7    order: VecDeque<String>,       // Keys in insertion order
8    remote_verification_interval: Duration,
9    capacity: usize,
10}
11
12impl JwtCache {
13    /// Create a new cache with given TTL and capacity
14    pub fn new(remote_verification_interval: Duration, capacity: usize) -> Self {
15        Self {
16            map: HashMap::with_capacity(capacity),
17            order: VecDeque::with_capacity(capacity),
18            remote_verification_interval,
19            capacity,
20        }
21    }
22
23    pub fn is_recent(&self, key: &str) -> bool {
24        self.map
25            .get(key)
26            .is_some_and(|t| t.elapsed() <= self.remote_verification_interval)
27    }
28
29    /// Record , updates timestamp or adds new entry
30    pub fn record(&mut self, key: String) {
31        // Remove expired entries first
32        self.remove_expired();
33
34        if self.map.contains_key(&key) {
35            // Update timestamp (no promotion in order)
36            self.map.insert(key.clone(), Instant::now());
37        } else {
38            // Evict oldest if over capacity
39            if self.map.len() >= self.capacity {
40                if let Some(oldest) = self.order.pop_front() {
41                    self.map.remove(&oldest);
42                }
43            }
44            self.map.insert(key.clone(), Instant::now());
45            self.order.push_back(key);
46        }
47    }
48
49    /// Remove expired entries
50    pub fn remove_expired(&mut self) {
51        let now = Instant::now();
52        let mut expired = Vec::new();
53
54        for key in &self.order {
55            if let Some(&last) = self.map.get(key).as_ref() {
56                if now.duration_since(last.to_owned()) > self.remote_verification_interval {
57                    expired.push(key.clone());
58                }
59            }
60        }
61
62        for key in expired {
63            self.map.remove(&key);
64            self.order.retain(|k| *k != key);
65        }
66    }
67}