Skip to main content

cortex_runtime/live/
refresh.rs

1//! REFRESH handler — re-render nodes and update the map.
2
3use crate::map::types::SiteMap;
4use serde::{Deserialize, Serialize};
5use std::collections::hash_map::DefaultHasher;
6use std::hash::{Hash, Hasher};
7
8/// Result of a refresh operation.
9#[derive(Debug, Clone, Serialize, Deserialize)]
10pub struct RefreshResult {
11    /// Number of nodes that were re-rendered.
12    pub updated_count: u32,
13    /// Indices of nodes whose content changed.
14    pub changed_nodes: Vec<u32>,
15}
16
17/// Parameters for a refresh operation.
18#[derive(Debug, Clone)]
19pub struct RefreshRequest {
20    /// Specific node indices to refresh.
21    pub nodes: Option<Vec<u32>>,
22    /// Refresh all nodes in a cluster.
23    pub cluster: Option<u32>,
24    /// Refresh nodes older than this many seconds.
25    pub stale_threshold: Option<f64>,
26}
27
28/// Determine which nodes to refresh based on the request parameters.
29pub fn select_nodes_to_refresh(map: &SiteMap, request: &RefreshRequest) -> Vec<u32> {
30    if let Some(ref nodes) = request.nodes {
31        return nodes.clone();
32    }
33
34    if let Some(cluster_id) = request.cluster {
35        return map
36            .cluster_assignments
37            .iter()
38            .enumerate()
39            .filter(|(_, &c)| c == cluster_id as u16)
40            .map(|(i, _)| i as u32)
41            .collect();
42    }
43
44    if let Some(threshold) = request.stale_threshold {
45        return map
46            .nodes
47            .iter()
48            .enumerate()
49            .filter(|(_, node)| {
50                // freshness is a u8 (0-255 maps to 0.0-1.0)
51                let freshness = node.freshness as f64 / 255.0;
52                freshness < threshold
53            })
54            .map(|(i, _)| i as u32)
55            .collect();
56    }
57
58    // Default: refresh all nodes
59    (0..map.nodes.len() as u32).collect()
60}
61
62/// Compute a content hash for a feature vector (to detect changes).
63pub fn feature_hash(features: &[f32; 128]) -> u64 {
64    let mut hasher = DefaultHasher::new();
65    for &f in features.iter() {
66        f.to_bits().hash(&mut hasher);
67    }
68    hasher.finish()
69}
70
71/// Compare old and new features to detect changes.
72pub fn detect_changes(
73    old_features: &[f32; 128],
74    new_features: &[f32; 128],
75    threshold: f32,
76) -> bool {
77    old_features
78        .iter()
79        .zip(new_features.iter())
80        .any(|(&old, &new)| (old - new).abs() > threshold)
81}