dynamo_runtime/
metadata_registry.rs1use std::collections::HashMap;
17use std::path::PathBuf;
18use std::sync::Arc;
19
20use parking_lot::RwLock;
21
22pub const BASE_SUFFIX: &str = "_base";
26
27type Key = (String, String, String);
29
30#[derive(Clone, Debug, Default)]
32pub struct MetadataArtifactRegistry {
33 entries: Arc<RwLock<HashMap<Key, PathBuf>>>,
34}
35
36impl MetadataArtifactRegistry {
37 pub fn new() -> Self {
38 Self {
39 entries: Arc::new(RwLock::new(HashMap::new())),
40 }
41 }
42
43 pub fn register(&self, slug: &str, suffix: &str, filename: &str, path: PathBuf) {
44 let mut entries = self.entries.write();
45 entries.insert(
46 (slug.to_string(), suffix.to_string(), filename.to_string()),
47 path,
48 );
49 tracing::debug!(slug, suffix, filename, "registered metadata artifact");
50 }
51
52 pub fn get(&self, slug: &str, suffix: &str, filename: &str) -> Option<PathBuf> {
53 let entries = self.entries.read();
54 entries
55 .get(&(slug.to_string(), suffix.to_string(), filename.to_string()))
56 .cloned()
57 }
58
59 pub fn unregister(&self, slug: &str, suffix: &str) {
61 let mut entries = self.entries.write();
62 entries.retain(|(s, sx, _), _| !(s == slug && sx == suffix));
63 }
64
65 pub fn len(&self) -> usize {
66 self.entries.read().len()
67 }
68
69 pub fn is_empty(&self) -> bool {
70 self.entries.read().is_empty()
71 }
72}
73
74#[cfg(test)]
75mod tests {
76 use super::*;
77
78 #[test]
79 fn register_get_roundtrip() {
80 let reg = MetadataArtifactRegistry::new();
81 let p = PathBuf::from("/tmp/tokenizer.json");
82 reg.register("llama-3-8b", "_base", "tokenizer.json", p.clone());
83
84 assert_eq!(reg.get("llama-3-8b", "_base", "tokenizer.json"), Some(p));
85 assert!(reg.get("llama-3-8b", "_base", "missing.json").is_none());
86 assert!(reg.get("llama-3-8b", "lora-v1", "tokenizer.json").is_none());
87 }
88
89 #[test]
90 fn unregister_only_removes_matching_suffix() {
91 let reg = MetadataArtifactRegistry::new();
92 reg.register("m", "_base", "config.json", PathBuf::from("/m/c"));
93 reg.register("m", "_base", "tokenizer.json", PathBuf::from("/m/t"));
94 reg.register("m", "lora-v1", "config.json", PathBuf::from("/m/c"));
95
96 reg.unregister("m", "_base");
97
98 assert!(reg.get("m", "_base", "config.json").is_none());
99 assert!(reg.get("m", "_base", "tokenizer.json").is_none());
100 assert_eq!(
102 reg.get("m", "lora-v1", "config.json"),
103 Some(PathBuf::from("/m/c"))
104 );
105 assert_eq!(reg.len(), 1);
106 }
107}