Skip to main content

greentic_flow/cache/
metadata.rs

1use anyhow::{Result, bail};
2use chrono::{DateTime, Utc};
3
4use crate::cache::engine_profile::EngineProfile;
5
6#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
7pub struct ArtifactMetadata {
8    pub schema_version: u32,
9    pub engine_profile_id: String,
10    pub wasmtime_version: String,
11    pub target_triple: String,
12    pub cpu_policy: String,
13    pub config_fingerprint: String,
14    pub wasm_digest: String,
15    pub artifact_bytes: u64,
16    pub created_at: String,
17    pub last_access_at: String,
18    pub hit_count: u64,
19}
20
21impl ArtifactMetadata {
22    pub fn new(profile: &EngineProfile, wasm_digest: String, artifact_bytes: u64) -> Self {
23        let now = Utc::now();
24        let ts = now.to_rfc3339();
25        Self {
26            schema_version: 1,
27            engine_profile_id: profile.engine_profile_id.clone(),
28            wasmtime_version: profile.wasmtime_version.clone(),
29            target_triple: profile.target_triple.clone(),
30            cpu_policy: profile.cpu_policy.as_str().to_string(),
31            config_fingerprint: profile.config_fingerprint.clone(),
32            wasm_digest,
33            artifact_bytes,
34            created_at: ts.clone(),
35            last_access_at: ts,
36            hit_count: 0,
37        }
38    }
39
40    pub fn validate_for_profile(&self, profile: &EngineProfile) -> Result<()> {
41        if self.schema_version != 1 {
42            bail!("cache metadata schema_version must be 1");
43        }
44        if self.engine_profile_id != profile.engine_profile_id {
45            bail!("cache metadata engine_profile_id mismatch");
46        }
47        if self.wasmtime_version != profile.wasmtime_version {
48            bail!("cache metadata wasmtime_version mismatch");
49        }
50        if self.target_triple != profile.target_triple {
51            bail!("cache metadata target_triple mismatch");
52        }
53        if self.cpu_policy != profile.cpu_policy.as_str() {
54            bail!("cache metadata cpu_policy mismatch");
55        }
56        if self.config_fingerprint != profile.config_fingerprint {
57            bail!("cache metadata config_fingerprint mismatch");
58        }
59        Ok(())
60    }
61
62    pub fn last_access_time(&self) -> Option<DateTime<Utc>> {
63        DateTime::parse_from_rfc3339(&self.last_access_at)
64            .ok()
65            .map(|dt| dt.with_timezone(&Utc))
66            .or_else(|| {
67                DateTime::parse_from_rfc3339(&self.created_at)
68                    .ok()
69                    .map(|dt| dt.with_timezone(&Utc))
70            })
71    }
72
73    pub fn touch(&mut self) {
74        self.last_access_at = Utc::now().to_rfc3339();
75        self.hit_count = self.hit_count.saturating_add(1);
76    }
77}