From b874d21cdaf88b71907ff6a91a96180b2a8c8d3e Mon Sep 17 00:00:00 2001 From: atlas Date: Fri, 9 Oct 2026 09:48:03 +0200 Subject: [PATCH] hive-c0re/swarm-*: drop clippy allows and dedupe unix_now + KV open_or_create No behaviour change. Casts replaced by try_from / Duration math; schedules.rs reuses agent_renewal::unix_now; the five swarm-queue-client KV open-or-create copies share one private kv::open_or_create. --- hive-c0re/src/stats/container_stats.rs | 20 +++---------- hive-c0re/src/stats/hive_stats.rs | 7 +---- hive-c0re/src/stats/otel_metrics.rs | 3 +- swarm-controller/src/schedules.rs | 7 +---- swarm-queue-client/src/agent_icon.rs | 28 +++++-------------- swarm-queue-client/src/agent_schedules.rs | 29 +++++-------------- swarm-queue-client/src/agent_status.rs | 28 +++++-------------- swarm-queue-client/src/kv.rs | 34 +++++++++++++++++++++++ swarm-queue-client/src/lib.rs | 3 ++ swarm-queue-client/src/status.rs | 28 +++++-------------- swarm-queue-client/src/wanted.rs | 20 ++----------- 11 files changed, 74 insertions(+), 133 deletions(-) create mode 100644 swarm-queue-client/src/kv.rs diff --git a/hive-c0re/src/stats/container_stats.rs b/hive-c0re/src/stats/container_stats.rs index b3137e9b..99b4a26a 100644 --- a/hive-c0re/src/stats/container_stats.rs +++ b/hive-c0re/src/stats/container_stats.rs @@ -222,16 +222,8 @@ pub async fn gather() -> Vec { let t0: Vec> = candidates.iter().map(|(_, d)| read_usage_usec(d)).collect(); sleep(CPU_SAMPLE).await; - #[allow( - clippy::cast_precision_loss, - reason = "CPU-utilisation math; the operands (core count, microsecond sample interval, cgroup time delta) stay well under f64's 2^53 exact-integer range, so no precision is lost" - )] - let nproc = host_nproc() as f64; - #[allow( - clippy::cast_precision_loss, - reason = "CPU-utilisation math; the operands (core count, microsecond sample interval, cgroup time delta) stay well under f64's 2^53 exact-integer range, so no precision is lost" - )] - let interval_usec = CPU_SAMPLE.as_micros() as f64; + let nproc = f64::from(u32::try_from(host_nproc()).unwrap_or(u32::MAX)); + let interval_secs = CPU_SAMPLE.as_secs_f64(); // Snapshot the slow disk cache once (cheap clone of a small map) so // the per-agent loop below is a plain map lookup — no `du` on this @@ -246,12 +238,8 @@ pub async fn gather() -> Vec { let usage_now = read_usage_usec(dir); let cpu_pct = match (t0[i], usage_now) { (Some(a), Some(b)) => { - #[allow( - clippy::cast_precision_loss, - reason = "CPU-utilisation math; the operands (core count, microsecond sample interval, cgroup time delta) stay well under f64's 2^53 exact-integer range, so no precision is lost" - )] - let delta = b.saturating_sub(a) as f64; - (delta / (interval_usec * nproc)) * 100.0 + let delta_secs = Duration::from_micros(b.saturating_sub(a)).as_secs_f64(); + (delta_secs / (interval_secs * nproc)) * 100.0 } _ => 0.0, }; diff --git a/hive-c0re/src/stats/hive_stats.rs b/hive-c0re/src/stats/hive_stats.rs index 5cdce915..dcec8c37 100644 --- a/hive-c0re/src/stats/hive_stats.rs +++ b/hive-c0re/src/stats/hive_stats.rs @@ -236,13 +236,8 @@ struct AgentAgg { skills: HashMap, } -#[allow( - clippy::cast_sign_loss, - clippy::cast_possible_truncation, - reason = "v.max(0) clamps to a non-negative value first, so the i64->u64 cast is exact: no sign loss, and no truncation since u64 covers all non-negative i64" -)] fn u64_from_i64(v: i64) -> u64 { - v.max(0) as u64 + u64::try_from(v).unwrap_or(0) } /// Aggregate one agent's turn-stats over `[from, now]`. Errors bubble diff --git a/hive-c0re/src/stats/otel_metrics.rs b/hive-c0re/src/stats/otel_metrics.rs index 35ac7ed6..bfb28f52 100644 --- a/hive-c0re/src/stats/otel_metrics.rs +++ b/hive-c0re/src/stats/otel_metrics.rs @@ -154,8 +154,7 @@ fn register_instruments(provider: &SdkMeterProvider, snapshot: Arc i64 { - std::time::SystemTime::now() - .duration_since(std::time::UNIX_EPOCH) - .map_or(0, |d| i64::try_from(d.as_secs()).unwrap_or(i64::MAX)) -} - #[cfg(test)] mod tests { use super::*; diff --git a/swarm-queue-client/src/agent_icon.rs b/swarm-queue-client/src/agent_icon.rs index 0186022a..1805b03d 100644 --- a/swarm-queue-client/src/agent_icon.rs +++ b/swarm-queue-client/src/agent_icon.rs @@ -62,27 +62,13 @@ pub async fn open_or_create( client: &async_nats::Client, ) -> Result { let js = async_nats::jetstream::new(client.clone()); - match js.get_key_value(BUCKET).await { - Ok(store) => Ok(store), - Err(e) => { - tracing::info!( - bucket = BUCKET, - reason = %e, - "agent-icon bucket not available, creating it" - ); - js.create_key_value(async_nats::jetstream::kv::Config { - bucket: BUCKET.to_owned(), - description: "Current icon published by each agent".to_owned(), - history: 1, - ..Default::default() - }) - .await - .map_err(|source| Error::CreateBucket { - bucket: BUCKET.to_owned(), - source, - }) - } - } + crate::kv::open_or_create( + &js, + BUCKET, + "agent-icon", + "Current icon published by each agent".to_owned(), + ) + .await } #[cfg(test)] diff --git a/swarm-queue-client/src/agent_schedules.rs b/swarm-queue-client/src/agent_schedules.rs index f3a26677..13537e8e 100644 --- a/swarm-queue-client/src/agent_schedules.rs +++ b/swarm-queue-client/src/agent_schedules.rs @@ -97,28 +97,13 @@ pub async fn open_or_create( client: &async_nats::Client, ) -> Result { let js = async_nats::jetstream::new(client.clone()); - match js.get_key_value(BUCKET).await { - Ok(store) => Ok(store), - Err(e) => { - tracing::info!( - bucket = BUCKET, - reason = %e, - "agent-schedule bucket not available, creating it" - ); - js.create_key_value(async_nats::jetstream::kv::Config { - bucket: BUCKET.to_owned(), - description: "Scheduled prompts the swarm controller declares for each agent" - .to_owned(), - history: 1, - ..Default::default() - }) - .await - .map_err(|source| crate::Error::CreateBucket { - bucket: BUCKET.to_owned(), - source, - }) - } - } + crate::kv::open_or_create( + &js, + BUCKET, + "agent-schedule", + "Scheduled prompts the swarm controller declares for each agent".to_owned(), + ) + .await } /// What reading one agent's key found. diff --git a/swarm-queue-client/src/agent_status.rs b/swarm-queue-client/src/agent_status.rs index 65104bc5..52ba59ff 100644 --- a/swarm-queue-client/src/agent_status.rs +++ b/swarm-queue-client/src/agent_status.rs @@ -109,27 +109,13 @@ pub async fn open_or_create( client: &async_nats::Client, ) -> Result { let js = async_nats::jetstream::new(client.clone()); - match js.get_key_value(BUCKET).await { - Ok(store) => Ok(store), - Err(e) => { - tracing::info!( - bucket = BUCKET, - reason = %e, - "agent-status bucket not available, creating it" - ); - js.create_key_value(async_nats::jetstream::kv::Config { - bucket: BUCKET.to_owned(), - description: "Last status snapshot offered by each agent".to_owned(), - history: 1, - ..Default::default() - }) - .await - .map_err(|source| Error::CreateBucket { - bucket: BUCKET.to_owned(), - source, - }) - } - } + crate::kv::open_or_create( + &js, + BUCKET, + "agent-status", + "Last status snapshot offered by each agent".to_owned(), + ) + .await } #[cfg(test)] diff --git a/swarm-queue-client/src/kv.rs b/swarm-queue-client/src/kv.rs new file mode 100644 index 00000000..9427a82a --- /dev/null +++ b/swarm-queue-client/src/kv.rs @@ -0,0 +1,34 @@ +//! The open-or-create sequence every KV bucket module shares. + +use crate::Error; + +/// Open `bucket`, creating it with `history: 1` and `description` when it +/// does not exist yet. `label` names the bucket in the creation log line. +pub(crate) async fn open_or_create( + js: &async_nats::jetstream::Context, + bucket: &str, + label: &str, + description: String, +) -> Result { + match js.get_key_value(bucket).await { + Ok(store) => Ok(store), + Err(e) => { + tracing::info!( + bucket, + reason = %e, + "{label} bucket not available, creating it" + ); + js.create_key_value(async_nats::jetstream::kv::Config { + bucket: bucket.to_owned(), + description, + history: 1, + ..Default::default() + }) + .await + .map_err(|source| Error::CreateBucket { + bucket: bucket.to_owned(), + source, + }) + } + } +} diff --git a/swarm-queue-client/src/lib.rs b/swarm-queue-client/src/lib.rs index eb6f1ae9..041fb7ac 100644 --- a/swarm-queue-client/src/lib.rs +++ b/swarm-queue-client/src/lib.rs @@ -201,6 +201,9 @@ pub mod agent_icon; /// writing needs `kv` and reading needs `agent-schedules`. pub mod agent_schedules; +#[cfg(feature = "kv")] +mod kv; + /// The subject the swarm controller publishes on when the hive-wide knowledge /// repository has changed. One writer, many readers — every hive subscribes. /// diff --git a/swarm-queue-client/src/status.rs b/swarm-queue-client/src/status.rs index 3e019e86..56b90c25 100644 --- a/swarm-queue-client/src/status.rs +++ b/swarm-queue-client/src/status.rs @@ -51,25 +51,11 @@ pub async fn open_or_create( client: &async_nats::Client, ) -> Result { let js = async_nats::jetstream::new(client.clone()); - match js.get_key_value(BUCKET).await { - Ok(store) => Ok(store), - Err(e) => { - tracing::info!( - bucket = BUCKET, - reason = %e, - "status bucket not available, creating it" - ); - js.create_key_value(async_nats::jetstream::kv::Config { - bucket: BUCKET.to_owned(), - description: "Last status snapshot offered by each hive".to_owned(), - history: 1, - ..Default::default() - }) - .await - .map_err(|source| Error::CreateBucket { - bucket: BUCKET.to_owned(), - source, - }) - } - } + crate::kv::open_or_create( + &js, + BUCKET, + "status", + "Last status snapshot offered by each hive".to_owned(), + ) + .await } diff --git a/swarm-queue-client/src/wanted.rs b/swarm-queue-client/src/wanted.rs index 4ebfcbe7..b10d8d7f 100644 --- a/swarm-queue-client/src/wanted.rs +++ b/swarm-queue-client/src/wanted.rs @@ -125,24 +125,8 @@ pub async fn open_or_create( ) -> Result { let js = async_nats::jetstream::new(client.clone()); let bucket = bucket(hive); - match js.get_key_value(&bucket).await { - Ok(store) => Ok(store), - Err(e) => { - tracing::info!( - %bucket, - reason = %e, - "wanted-state bucket not available, creating it" - ); - js.create_key_value(async_nats::jetstream::kv::Config { - bucket: bucket.clone(), - description: format!("Agent set the swarm controller declares for hive {hive}"), - history: 1, - ..Default::default() - }) - .await - .map_err(|source| Error::CreateBucket { bucket, source }) - } - } + let description = format!("Agent set the swarm controller declares for hive {hive}"); + crate::kv::open_or_create(&js, &bucket, "wanted-state", description).await } /// Open the wanted-state bucket for reading, or `None` when it does not exist.