Watch
0
0
Fork
You've already forked hyperhive
0
hyperhive/swarm-wire/src/agent_closures.rs

85 lines
2.9 KiB
Rust

//! The per-agent closure KV bucket: one key per agent, holding the latest
//! system closure the swarm builder built for it from the swarm meta flake.
//!
//! **swarm-controller is the only writer**, and creates the bucket on its first
//! write. It writes a key from a builder's `Built` reply and from nothing else,
//! so a failed build leaves the previous record in place. The builder holds no
//! grant on this bucket.
//!
//! Keyed by the agent alone, like [`crate::agent_limits`]: an agent can move
//! between hives, and its closure goes with it.
/// The KV bucket closures are recorded in, keyed by agent name.
pub const BUCKET: &str = "agent-closures";
/// The stream backing [`BUCKET`]. `create_key_value` prefixes `KV_`.
pub const STREAM: &str = "KV_agent-closures";
/// The subject `agent`'s entry is stored under.
#[must_use]
pub fn key_subject(agent: &str) -> String {
format!("$KV.{BUCKET}.{agent}")
}
/// One agent's latest green build: the value under `BUCKET`/`<agent>`.
#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
pub struct AgentClosure {
/// The `internal/meta` commit the closure was built from.
pub meta_rev: String,
/// The system closure's store path, in the builder host's store.
pub store_path: String,
/// The platform the closure was built for.
pub system: String,
/// When the controller recorded the build, in unix seconds.
pub built_unix: i64,
/// Whether the builder pushed the closure to the binary cache. A record
/// written before the field existed reads as false.
#[serde(default)]
pub cached: bool,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn names_are_pinned() {
assert_eq!(STREAM, format!("KV_{BUCKET}"));
assert_eq!(key_subject("iris"), "$KV.agent-closures.iris");
}
#[test]
fn the_record_serializes_as_pinned() {
let value = AgentClosure {
meta_rev: "abc".to_owned(),
store_path: "/nix/store/x".to_owned(),
system: "x86_64-linux".to_owned(),
built_unix: 7,
cached: true,
};
let wire = serde_json::json!({
"meta_rev": "abc",
"store_path": "/nix/store/x",
"system": "x86_64-linux",
"built_unix": 7,
"cached": true,
});
assert_eq!(serde_json::to_value(&value).expect("encodes"), wire);
assert_eq!(
serde_json::from_value::<AgentClosure>(wire).expect("decodes"),
value
);
}
#[test]
fn a_record_without_the_field_reads_as_not_cached() {
let old = serde_json::json!({
"meta_rev": "abc",
"store_path": "/nix/store/x",
"system": "x86_64-linux",
"built_unix": 7,
});
let record = serde_json::from_value::<AgentClosure>(old).expect("decodes");
assert!(!record.cached);
}
}