1use std::collections::HashMap;
2use std::time::{Duration, Instant};
3
4use crate::{client::JiraClient, error::Result, model::field::Field};
5
6const TTL: Duration = Duration::from_secs(300); struct CacheEntry {
9 fields: Vec<Field>,
10 fetched_at: Instant,
11}
12
13impl CacheEntry {
14 fn is_fresh(&self) -> bool {
15 self.fetched_at.elapsed() < TTL
16 }
17}
18
19pub struct FieldCache {
21 entries: HashMap<String, CacheEntry>,
22}
23
24impl FieldCache {
25 pub fn new() -> Self {
26 Self {
27 entries: HashMap::new(),
28 }
29 }
30
31 pub async fn get_or_fetch(
33 &mut self,
34 client: &JiraClient,
35 project_key: &str,
36 issue_type_id: &str,
37 ) -> Result<Vec<Field>> {
38 let key = format!("{project_key}:{issue_type_id}");
39
40 if let Some(entry) = self.entries.get(&key) {
41 if entry.is_fresh() {
42 return Ok(entry.fields.clone());
43 }
44 }
45
46 let fields = client
47 .get_fields_for_issue_type(project_key, issue_type_id)
48 .await?;
49
50 self.entries.insert(
51 key,
52 CacheEntry {
53 fields: fields.clone(),
54 fetched_at: Instant::now(),
55 },
56 );
57
58 Ok(fields)
59 }
60}
61
62impl Default for FieldCache {
63 fn default() -> Self {
64 Self::new()
65 }
66}