axum_oidc_layer/cache/
memory.rs1use std::{
4 collections::HashMap,
5 sync::{Arc, RwLock},
6 time::{Duration, Instant},
7};
8
9use super::JwksCache;
10
11#[derive(Debug)]
17pub struct InMemoryCache {
18 storage: Arc<RwLock<HashMap<String, CacheEntry>>>,
19}
20
21#[derive(Debug, Clone)]
23struct CacheEntry {
24 data: String,
25 expires_at: Instant,
26}
27
28impl Default for InMemoryCache {
29 fn default() -> Self {
30 Self::new()
31 }
32}
33
34impl InMemoryCache {
35 #[must_use]
37 pub fn new() -> Self {
38 Self {
39 storage: Arc::new(RwLock::new(HashMap::new())),
40 }
41 }
42
43 fn cleanup_expired(&self) {
48 if let Ok(mut storage) = self.storage.write() {
49 let now = Instant::now();
50 storage.retain(|_, entry| entry.expires_at > now);
51 }
52 }
53}
54
55impl JwksCache for InMemoryCache {
56 fn get(&self, key: &str) -> Option<String> {
57 self.cleanup_expired();
58
59 self.storage.read().map_or(None, |storage| {
60 storage
61 .get(key)
62 .filter(|entry| entry.expires_at > Instant::now())
63 .map(|entry| entry.data.clone())
64 })
65 }
66
67 fn set(&self, key: &str, value: String, ttl: Duration) {
68 if let Ok(mut storage) = self.storage.write() {
69 let entry = CacheEntry {
70 data: value,
71 expires_at: Instant::now() + ttl,
72 };
73 storage.insert(key.to_string(), entry);
74 }
75 }
76}