greentic_flow/cache/
metadata.rs1use 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}