summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJesper Jensen <jesper@jnsn.dev>2026-02-08 13:38:57 +0100
committerJesper Jensen <jesper@jnsn.dev>2026-02-08 13:38:57 +0100
commit7fb61dfbca0bf1ccc09d40ff2e3b76e2515ff815 (patch)
tree009242f0831679e2d44287da3cfc064e2427e58f /src
parentc95756dda52d8817b6955080be473073267ec17f (diff)
Avoid fetching tags multiple times
What a dumb bug
Diffstat (limited to 'src')
-rw-r--r--src/registry.rs6
-rw-r--r--src/updater.rs36
2 files changed, 42 insertions, 0 deletions
diff --git a/src/registry.rs b/src/registry.rs
index b18c1eb..173f8a7 100644
--- a/src/registry.rs
+++ b/src/registry.rs
@@ -334,6 +334,7 @@ struct StubTag {
#[cfg(test)]
pub struct StubRegistry {
entries: RefCell<Vec<StubTag>>,
+ pub tags_calls: RefCell<HashMap<(String, String), usize>>,
}
#[cfg(test)]
@@ -341,6 +342,7 @@ impl Default for StubRegistry {
fn default() -> Self {
return StubRegistry {
entries: RefCell::new(vec![]),
+ tags_calls: RefCell::new(HashMap::new()),
};
}
}
@@ -369,6 +371,10 @@ impl StubRegistry {
#[cfg(test)]
impl Registries for StubRegistry {
fn get_tags(&self, registry: &str, image: &str) -> Option<Vec<String>> {
+ *self.tags_calls.borrow_mut()
+ .entry((registry.to_string(), image.to_string()))
+ .or_insert(0) += 1;
+
let mut tags = vec![];
let mut found = false;
diff --git a/src/updater.rs b/src/updater.rs
index a21f378..7b63bf7 100644
--- a/src/updater.rs
+++ b/src/updater.rs
@@ -103,11 +103,25 @@ pub fn update_images(now: &DateTime<Utc>, db: &dyn Db, reg: &dyn Registries, fil
db.delete_tag(image_id, gone);
}
db.update_last_checked(image_id, now);
+ // @CLEANUP: Propagate the update to other instances. We should really avoid
+ // this situation in the first place
+ for j in (i + 1)..image_ids.len() {
+ if image_ids[j] == image_id {
+ last_checkeds[j] = *now;
+ }
+ }
Ok((fetched_tags, None))
}
None => {
db.update_last_checked(image_id, now);
+ // @CLEANUP: Propagate the update to other instances. We should really avoid
+ // this situation in the first place
+ for j in (i + 1)..image_ids.len() {
+ if image_ids[j] == image_id {
+ last_checkeds[j] = *now;
+ }
+ }
Err(format!("image not found: {}", image_name))
}
}
@@ -619,4 +633,26 @@ mod tests {
assert!(db.get_image("registry.hub.docker.com", "redis").is_some());
assert!(db.get_tags_sorted(2).is_empty());
}
+
+ #[test]
+ fn same_image_multiple_files_fetches_twice() {
+ crate::metrics::init();
+ let now = Utc.with_ymd_and_hms(2000, 1, 1, 0, 0, 0).unwrap();
+ let db = StubDb::default();
+ let reg = StubRegistry::default();
+
+ reg.add_tag("registry.hub.docker.com", "nginx", "1.21", "sha256:0000000000000000000000000000000000000000000000000000000000000001");
+ reg.add_tag("registry.hub.docker.com", "nginx", "1.22", "sha256:0000000000000000000000000000000000000000000000000000000000000002");
+
+ let files = vec![
+ FileInput { path: "/a".into(), content: "image: nginx:1.21".into(), images: vec![7..17] },
+ FileInput { path: "/b".into(), content: "image: nginx:1.21".into(), images: vec![7..17] },
+ ];
+ let mut outcomes = vec![];
+ update_images(&now, &db, &reg, &files, &mut outcomes);
+
+ assert_eq!(outcomes[0].as_ref().unwrap()[0].content, "1.22");
+ assert_eq!(outcomes[1].as_ref().unwrap()[0].content, "1.22");
+ assert_eq!(reg.tags_calls.borrow()[&("registry.hub.docker.com".to_string(), "nginx".to_string())], 1);
+ }
}