Track CAS providers

This commit is contained in:
Eric Wendland 2026-05-19 15:37:02 +02:00
commit c9803ea7f2
8 changed files with 161 additions and 11 deletions

View file

@ -100,6 +100,13 @@ impl Store {
hash TEXT PRIMARY KEY,
pinned_at_ms INTEGER NOT NULL
);
CREATE TABLE IF NOT EXISTS cas_providers (
hash TEXT NOT NULL,
peer_node_id TEXT NOT NULL,
endpoint_id TEXT NOT NULL,
last_seen_ms INTEGER NOT NULL,
PRIMARY KEY(hash, peer_node_id)
);
CREATE TABLE IF NOT EXISTS kv_stores (
kv_id TEXT PRIMARY KEY,
resource_id TEXT NOT NULL,
@ -746,6 +753,39 @@ impl Store {
.map_err(StoreError::from)
}
pub fn record_cas_provider(
&self,
hash: &str,
peer_node_id: &str,
endpoint_id: &str,
) -> Result<(), StoreError> {
self.conn.execute(
r#"INSERT OR REPLACE INTO cas_providers(hash, peer_node_id, endpoint_id, last_seen_ms)
VALUES (?1, ?2, ?3, ?4)"#,
params![hash, peer_node_id, endpoint_id, now_ms()],
)?;
Ok(())
}
pub fn list_cas_providers(&self, hash: &str) -> Result<Vec<CasProvider>, StoreError> {
let mut stmt = self.conn.prepare(
r#"SELECT hash, peer_node_id, endpoint_id, last_seen_ms
FROM cas_providers
WHERE hash = ?1
ORDER BY last_seen_ms DESC, peer_node_id"#,
)?;
let rows = stmt.query_map(params![hash], |row| {
Ok(CasProvider {
hash: row.get(0)?,
peer_node_id: row.get(1)?,
endpoint_id: row.get(2)?,
last_seen_ms: row.get(3)?,
})
})?;
rows.collect::<Result<Vec<_>, _>>()
.map_err(StoreError::from)
}
pub fn upsert_peer_card(&self, peer_card: &StoredPeerCard) -> Result<(), StoreError> {
self.conn.execute(
"INSERT OR REPLACE INTO peer_cards(peer_id, card_json, updated_at_ms) VALUES (?1, ?2, ?3)",
@ -1132,6 +1172,14 @@ pub struct StoredResource {
pub status: String,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct CasProvider {
pub hash: String,
pub peer_node_id: String,
pub endpoint_id: String,
pub last_seen_ms: i64,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct StoredDbResource {
pub db_id: String,
@ -1452,6 +1500,30 @@ mod tests {
assert!(store.list_cas_pins().expect("pins").is_empty());
}
#[test]
fn cas_providers_roundtrip_by_hash() {
let store = Store::open_memory().expect("open");
let hash = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef";
store
.record_cas_provider(hash, "node:laptop", "endpoint:laptop")
.expect("record provider");
let providers = store.list_cas_providers(hash).expect("list providers");
assert_eq!(providers.len(), 1);
assert_eq!(providers[0].hash, hash);
assert_eq!(providers[0].peer_node_id, "node:laptop");
assert_eq!(providers[0].endpoint_id, "endpoint:laptop");
assert!(
store
.list_cas_providers(
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
)
.expect("list missing")
.is_empty()
);
}
#[test]
fn deleting_cas_object_removes_pin_metadata() {
let store = Store::open_memory().expect("open");