use std::collections::HashMap;
use std::sync::Mutex;
use std::time::{Duration, Instant};
use crate::{client::JiraClient, error::Result, model::field::Field};
const TTL: Duration = Duration::from_secs(300);
struct CacheEntry {
fields: Vec<Field>,
fetched_at: Instant,
}
impl CacheEntry {
fn is_fresh(&self) -> bool {
self.fetched_at.elapsed() < TTL
}
}
pub struct FieldCache {
entries: Mutex<HashMap<String, CacheEntry>>,
}
impl FieldCache {
pub fn new() -> Self {
Self {
entries: Mutex::new(HashMap::new()),
}
}
pub async fn get_or_fetch(
&self,
client: &JiraClient,
project_key: &str,
issue_type_id: &str,
) -> Result<Vec<Field>> {
let key = format!("{project_key}:{issue_type_id}");
{
let entries = self.entries.lock().expect("FieldCache mutex poisoned");
if let Some(entry) = entries.get(&key) {
if entry.is_fresh() {
return Ok(entry.fields.clone());
}
}
}
let fields = client
.get_fields_for_issue_type(project_key, issue_type_id)
.await?;
{
let mut entries = self.entries.lock().expect("FieldCache mutex poisoned");
entries.insert(
key,
CacheEntry {
fields: fields.clone(),
fetched_at: Instant::now(),
},
);
}
Ok(fields)
}
}
impl Default for FieldCache {
fn default() -> Self {
Self::new()
}
}