cherenkov/model/index/
gc.rs1use super::{GcReport, ModelIndex, Removal, lookup, store};
2use anyhow::{Context, Result, ensure};
3
4impl ModelIndex {
5 pub fn remove(&self, reference: &str, source_only: bool) -> Result<Removal> {
9 let mut catalog = self.lock()?;
10 let model = lookup(&catalog.value, reference)?.clone();
11 let mut released = Vec::new();
12
13 if source_only {
14 let prepared = model
15 .prepared
16 .as_ref()
17 .context("prepare the model before releasing source copies")?;
18 let artifact = &catalog.value.artifacts[prepared];
19
20 ensure!(artifact.ready, "prepared artifact is incomplete");
21
22 crate::model::Checkpoint::open(&self.artifact_path(artifact))
23 .context("validate the prepared model before releasing its source")?;
24
25 if let Some(id) = model.retained_source {
26 released.push(id);
27 }
28
29 catalog
30 .value
31 .models
32 .get_mut(&model.id)
33 .unwrap()
34 .retained_source = None;
35 } else {
36 released.extend(model.prepared);
37 released.extend(model.retained_source);
38 catalog.value.models.remove(&model.id);
39 }
40
41 catalog.save()?;
42
43 Ok(Removal {
44 id: model.id,
45 source_only,
46 released_artifacts: released,
47 })
48 }
49
50 pub fn gc(&self, dry_run: bool) -> Result<GcReport> {
54 if !self.paths.data.join("index.json").exists() {
55 return Ok(GcReport {
56 dry_run,
57 ..Default::default()
58 });
59 }
60
61 let mut catalog = self.lock()?;
62 let candidates: Vec<_> = catalog
63 .value
64 .artifacts
65 .values()
66 .filter(|a| store::references(&catalog.value, &a.id) == 0)
67 .cloned()
68 .collect();
69 let mut report = GcReport {
70 dry_run,
71 ..Default::default()
72 };
73
74 for artifact in candidates {
75 let lease = self.lease_file(&artifact.id)?;
76
77 if lease.try_lock().is_err() {
78 report.leased.push(artifact.id);
79
80 continue;
81 }
82
83 if artifact.external.is_none() {
84 let path = self.artifact_root(&artifact.id);
85 report.candidate_bytes += store::bytes(&path)?;
86
87 if !dry_run && path.exists() {
88 std::fs::remove_dir_all(path)?;
89 }
90 }
91
92 report.artifacts.push(artifact.id.clone());
93
94 if !dry_run {
95 catalog.value.artifacts.remove(&artifact.id);
96 }
97 }
98
99 if !dry_run {
100 catalog.save()?;
101 }
102
103 Ok(report)
104 }
105}