use std::collections::HashMap;
use std::sync::Arc;
use std::time::{Duration, Instant};
use adk_core::AdkError;
use async_trait::async_trait;
use tokio::sync::RwLock;
use super::provider::SecretProvider;
struct CachedEntry {
value: String,
expires_at: Instant,
}
pub struct CachedSecretProvider<P: SecretProvider> {
inner: P,
cache: Arc<RwLock<HashMap<String, CachedEntry>>>,
ttl: Duration,
}
impl<P: SecretProvider> CachedSecretProvider<P> {
pub fn new(inner: P, ttl: Duration) -> Self {
Self { inner, cache: Arc::new(RwLock::new(HashMap::new())), ttl }
}
}
#[async_trait]
impl<P: SecretProvider> SecretProvider for CachedSecretProvider<P> {
async fn get_secret(&self, name: &str) -> Result<String, AdkError> {
{
let cache = self.cache.read().await;
if let Some(entry) = cache.get(name) {
if entry.expires_at > Instant::now() {
return Ok(entry.value.clone());
}
}
}
let value = self.inner.get_secret(name).await?;
{
let mut cache = self.cache.write().await;
cache.insert(
name.to_string(),
CachedEntry { value: value.clone(), expires_at: Instant::now() + self.ttl },
);
}
Ok(value)
}
}