summaryrefslogtreecommitdiff
path: root/src/db.rs
diff options
context:
space:
mode:
authorJesper Jensen <jesper@jnsn.dev>2026-02-08 16:28:37 +0100
committerJesper Jensen <jesper@jnsn.dev>2026-02-08 16:28:37 +0100
commit0fd24af76e57a946129f7f9943cb61771e00c1b3 (patch)
tree71c9a63e4af20144fd2942392fcc58a208036fc7 /src/db.rs
parent7fb61dfbca0bf1ccc09d40ff2e3b76e2515ff815 (diff)
Replace fetch time with expiry time
This should make it easier (possible) to query for expired images
Diffstat (limited to 'src/db.rs')
-rw-r--r--src/db.rs48
1 files changed, 27 insertions, 21 deletions
diff --git a/src/db.rs b/src/db.rs
index ae6073f..c914769 100644
--- a/src/db.rs
+++ b/src/db.rs
@@ -4,11 +4,11 @@ use rusqlite::OptionalExtension;
pub trait Db {
fn get_image(&self, registry: &str, image: &str) -> Option<(i64, DateTime<Utc>)>;
- fn insert_image(&self, registry: &str, image: &str, last_checked: &DateTime<Utc>) -> i64;
+ fn insert_image(&self, registry: &str, image: &str, expires_at: &DateTime<Utc>) -> i64;
fn get_tags_sorted(&self, image_id: i64) -> Vec<String>;
fn delete_tag(&self, image_id: i64, tag: &str);
fn insert_tag(&self, image_id: i64, tag: &str, fetched_at: &DateTime<Utc>);
- fn update_last_checked(&self, image_id: i64, last_checked: &DateTime<Utc>);
+ fn set_expires_at(&self, image_id: i64, expires_at: &DateTime<Utc>);
fn get_tag_digest(&self, image_id: i64, tag: &str) -> Option<String>;
fn update_tag_digest(&self, image_id: i64, tag: &str, digest: &str, fetched_at: &DateTime<Utc>);
}
@@ -97,6 +97,12 @@ impl SqliteDb {
conn.execute("INSERT INTO migrations(id) VALUES (?1)", (6, )).unwrap();
}
+ if newest_migration < 7 {
+ conn.execute("ALTER TABLE images RENAME COLUMN last_checked TO expires_at", ()).unwrap();
+ conn.execute("UPDATE images SET expires_at = datetime(expires_at, '+1440 minutes')", ()).unwrap();
+ conn.execute("INSERT INTO migrations(id) VALUES (?1)", (7, )).unwrap();
+ }
+
return SqliteDb { conn };
}
}
@@ -105,7 +111,7 @@ impl Db for SqliteDb {
fn get_image(&self, registry: &str, image: &str) -> Option<(i64, DateTime<Utc>)> {
let _timer = crate::metrics::get().db_query_duration.start_timer();
return self.conn.query_row("
- SELECT id, last_checked FROM images
+ SELECT id, expires_at FROM images
WHERE registry = ?1 AND image = ?2
", (registry, image), |row| Ok((
row.get::<_, i64>(0)?,
@@ -113,11 +119,11 @@ impl Db for SqliteDb {
))).optional().unwrap();
}
- fn insert_image(&self, registry: &str, image: &str, last_checked: &DateTime<Utc>) -> i64 {
+ fn insert_image(&self, registry: &str, image: &str, expires_at: &DateTime<Utc>) -> i64 {
let _timer = crate::metrics::get().db_query_duration.start_timer();
self.conn.execute("
- INSERT INTO images(registry, image, last_checked) VALUES (?1, ?2, ?3)
- ", (registry, image, last_checked)).unwrap();
+ INSERT INTO images(registry, image, expires_at) VALUES (?1, ?2, ?3)
+ ", (registry, image, expires_at)).unwrap();
return self.conn.last_insert_rowid();
}
@@ -144,9 +150,9 @@ impl Db for SqliteDb {
(image_id, tag, fetched_at)).unwrap();
}
- fn update_last_checked(&self, image_id: i64, last_checked: &DateTime<Utc>) {
+ fn set_expires_at(&self, image_id: i64, expires_at: &DateTime<Utc>) {
let _timer = crate::metrics::get().db_query_duration.start_timer();
- self.conn.execute("UPDATE images SET last_checked = ?1 WHERE id = ?2", (last_checked, image_id)).unwrap();
+ self.conn.execute("UPDATE images SET expires_at = ?1 WHERE id = ?2", (expires_at, image_id)).unwrap();
}
fn get_tag_digest(&self, image_id: i64, tag: &str) -> Option<String> {
@@ -184,18 +190,18 @@ impl Default for StubDb {
#[cfg(test)]
impl Db for StubDb {
fn get_image(&self, registry: &str, image: &str) -> Option<(i64, DateTime<Utc>)> {
- for (r, i, id, last_checked) in self.images.borrow().iter() {
+ for (r, i, id, expires_at) in self.images.borrow().iter() {
if r == registry && i == image {
- return Some((*id, *last_checked));
+ return Some((*id, *expires_at));
}
}
return None;
}
- fn insert_image(&self, registry: &str, image: &str, last_checked: &DateTime<Utc>) -> i64 {
+ fn insert_image(&self, registry: &str, image: &str, expires_at: &DateTime<Utc>) -> i64 {
let id = *self.next_id.borrow();
*self.next_id.borrow_mut() += 1;
- self.images.borrow_mut().push((registry.to_string(), image.to_string(), id, last_checked.clone()));
+ self.images.borrow_mut().push((registry.to_string(), image.to_string(), id, expires_at.clone()));
return id;
}
@@ -218,10 +224,10 @@ impl Db for StubDb {
self.tags.borrow_mut().push((image_id, tag.to_string(), None, fetched_at.clone()));
}
- fn update_last_checked(&self, image_id: i64, last_checked: &DateTime<Utc>) {
- for (_, _, id, lc) in self.images.borrow_mut().iter_mut() {
+ fn set_expires_at(&self, image_id: i64, expires_at: &DateTime<Utc>) {
+ for (_, _, id, ea) in self.images.borrow_mut().iter_mut() {
if *id == image_id {
- *lc = last_checked.clone();
+ *ea = expires_at.clone();
return;
}
}
@@ -295,11 +301,11 @@ mod tests {
assert_eq!(db.get_tags_sorted(id), vec!["2.0"]);
}
- fn test_update_last_checked(db: &dyn Db) {
+ fn test_set_expires_at(db: &dyn Db) {
let t1 = Utc.with_ymd_and_hms(2000, 1, 1, 0, 0, 0).unwrap();
let t2 = Utc.with_ymd_and_hms(2000, 1, 1, 1, 0, 0).unwrap();
let id = db.insert_image("docker.io", "nginx", &t1);
- db.update_last_checked(id, &t2);
+ db.set_expires_at(id, &t2);
assert_eq!(db.get_image("docker.io", "nginx").unwrap().1, t2);
}
@@ -391,15 +397,15 @@ mod tests {
}
#[test]
- fn conformance_stub_update_last_checked() {
- test_update_last_checked(&StubDb::default());
+ fn conformance_stub_set_expires_at() {
+ test_set_expires_at(&StubDb::default());
}
#[test]
- fn conformance_sqlite_update_last_checked() {
+ fn conformance_sqlite_set_expires_at() {
crate::metrics::init();
let dir = tempfile::tempdir().unwrap();
- test_update_last_checked(&SqliteDb::new(&dir.path().join("db.sqlite")));
+ test_set_expires_at(&SqliteDb::new(&dir.path().join("db.sqlite")));
}
#[test]