Files
clawmates/crates/cm-db/src/repo/node_tools.rs
T
osobhandClaude Opus 4.8 96d1409a23
ci / gates (push) Successful in 6s
ci / frontend (push) Successful in 24s
ci / rust (push) Failing after 2m39s
ci / e2e (push) Has been skipped
style: cargo fmt --all
Apply rustfmt (toolchain 1.96.0) to satisfy the CI Format check.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-27 11:54:28 -07:00

74 lines
2.2 KiB
Rust

//! Per-node installed dev-tool versions (probed by the daemon) and the latest
//! upstream version per tool (filled by a nightly checker). Drives the fleet
//! UI's "update available" badges.
use std::collections::HashMap;
use cm_domain::NodeId;
use sqlx::{PgPool, Row};
use crate::DbError;
/// Replace a node's reported tool versions with `tools` (tool, version).
pub async fn upsert(
pool: &PgPool,
node_id: NodeId,
tools: &[(String, String)],
) -> Result<(), DbError> {
for (tool, version) in tools {
sqlx::query(
"INSERT INTO node_tools (node_id, tool, version, updated_at)
VALUES ($1, $2, $3, now())
ON CONFLICT (node_id, tool) DO UPDATE SET version = excluded.version, updated_at = now()",
)
.bind(node_id.as_uuid())
.bind(tool)
.bind(version)
.execute(pool)
.await?;
}
Ok(())
}
/// A node's installed tool versions as `(tool, version)`.
pub async fn list(pool: &PgPool, node_id: NodeId) -> Result<Vec<(String, String)>, DbError> {
let rows = sqlx::query("SELECT tool, version FROM node_tools WHERE node_id = $1")
.bind(node_id.as_uuid())
.fetch_all(pool)
.await?;
Ok(rows
.into_iter()
.map(|r| (r.get::<String, _>("tool"), r.get::<String, _>("version")))
.collect())
}
/// Record the latest upstream version for a tool.
pub async fn set_latest(pool: &PgPool, tool: &str, latest: &str) -> Result<(), DbError> {
sqlx::query(
"INSERT INTO tool_latest (tool, latest_version, checked_at)
VALUES ($1, $2, now())
ON CONFLICT (tool) DO UPDATE SET latest_version = excluded.latest_version, checked_at = now()",
)
.bind(tool)
.bind(latest)
.execute(pool)
.await?;
Ok(())
}
/// All known latest versions, keyed by tool.
pub async fn all_latest(pool: &PgPool) -> Result<HashMap<String, String>, DbError> {
let rows = sqlx::query("SELECT tool, latest_version FROM tool_latest")
.fetch_all(pool)
.await?;
Ok(rows
.into_iter()
.map(|r| {
(
r.get::<String, _>("tool"),
r.get::<String, _>("latest_version"),
)
})
.collect())
}