use std::time::Duration; use ::cache::Cache; use serde::Serialize; use serde::de::DeserializeOwned; use crate::share::errors::GitError; pub const REV_TTL: Duration = Duration::from_secs(60); pub const ANALYSIS_TTL: Duration = Duration::from_secs(600); pub const IMMUTABLE_TTL: Duration = Duration::from_secs(30 * 24 * 3600); pub fn sanitize_key(k: &str) -> String { let mut out = String::with_capacity(k.len()); for c in k.chars() { if c.is_ascii_alphanumeric() || matches!(c, '-' | '_' | '.' | ':' | '/') { out.push(c); } else { out.push('_'); } } out } pub async fn cached_fetch( cache: &Cache, key: &str, ttl: Duration, fetch: F, ) -> Result where V: Serialize + DeserializeOwned, F: FnOnce() -> Fut, Fut: std::future::Future>, { let sanitized = sanitize_key(key); if let Ok(Some(cached)) = cache.get_json::(&sanitized).await { return Ok(cached); } let val = fetch().await?; let _ = cache.set_json_ex(&sanitized, &val, ttl).await; Ok(val) }