Load cached keys from disk (offline fallback on startup).
(&self)
| 105 | |
| 106 | /// Load cached keys from disk (offline fallback on startup). |
| 107 | pub fn load_from_disk(&self) { |
| 108 | let Some(ref path) = self.disk_path else { |
| 109 | return; |
| 110 | }; |
| 111 | |
| 112 | let disk_path = Path::new(path); |
| 113 | if !disk_path.exists() { |
| 114 | return; |
| 115 | } |
| 116 | |
| 117 | let data = match std::fs::read_to_string(disk_path) { |
| 118 | Ok(d) => d, |
| 119 | Err(e) => { |
| 120 | tracing::warn!(path = %path, error = %e, "failed to read JWKS disk cache"); |
| 121 | return; |
| 122 | } |
| 123 | }; |
| 124 | |
| 125 | let disk_cache: HashMap<String, Vec<DiskKeyEntry>> = match sonic_rs::from_str(&data) { |
| 126 | Ok(c) => c, |
| 127 | Err(e) => { |
| 128 | tracing::warn!(error = %e, "failed to parse JWKS disk cache"); |
| 129 | return; |
| 130 | } |
| 131 | }; |
| 132 | |
| 133 | let now = Instant::now(); |
| 134 | let mut providers = self.providers.write().unwrap_or_else(|p| p.into_inner()); |
| 135 | |
| 136 | for (provider_name, entries) in disk_cache { |
| 137 | let key_map: HashMap<String, VerificationKey> = entries |
| 138 | .into_iter() |
| 139 | .filter_map(|e| e.to_verification_key()) |
| 140 | .map(|k| (k.kid.clone(), k)) |
| 141 | .collect(); |
| 142 | |
| 143 | if !key_map.is_empty() { |
| 144 | tracing::info!( |
| 145 | provider = %provider_name, |
| 146 | keys = key_map.len(), |
| 147 | "loaded JWKS keys from disk cache" |
| 148 | ); |
| 149 | providers.insert( |
| 150 | provider_name, |
| 151 | ProviderKeys { |
| 152 | keys: key_map, |
| 153 | fetched_at: now, |
| 154 | last_refetch_attempt: now, |
| 155 | }, |
| 156 | ); |
| 157 | } |
| 158 | } |
| 159 | } |
| 160 | |
| 161 | /// Persist current cache to disk. |
| 162 | fn persist_to_disk( |