Skip to main content

arms/ports/
latency.rs

1//! # Latency Port
2//!
3//! Trait for runtime latency measurement and adaptation.
4//!
5//! This enables the model to know its actual retrieval constraints:
6//! - How fast is the hot tier right now?
7//! - How much budget do I have for retrieval?
8//! - Should I use fewer, faster retrievals or more, slower ones?
9
10use std::time::Duration;
11
12/// Storage tier levels
13#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
14pub enum Tier {
15    /// RAM storage - fastest
16    Hot,
17    /// NVMe storage - fast
18    Warm,
19    /// Archive storage - slow
20    Cold,
21}
22
23impl Tier {
24    /// Get expected latency range for this tier
25    pub fn expected_latency(&self) -> (Duration, Duration) {
26        match self {
27            Tier::Hot => (Duration::from_micros(1), Duration::from_millis(1)),
28            Tier::Warm => (Duration::from_millis(1), Duration::from_millis(10)),
29            Tier::Cold => (Duration::from_millis(10), Duration::from_millis(100)),
30        }
31    }
32}
33
34/// Latency measurement result
35#[derive(Debug, Clone)]
36pub struct LatencyMeasurement {
37    /// The tier that was measured
38    pub tier: Tier,
39
40    /// Measured latency for a single operation
41    pub latency: Duration,
42
43    /// Throughput (operations per second) if measured
44    pub throughput_ops: Option<f64>,
45
46    /// Timestamp of measurement
47    pub measured_at: std::time::Instant,
48}
49
50/// Budget allocation for retrieval operations
51#[derive(Debug, Clone)]
52pub struct LatencyBudget {
53    /// Total time budget for this retrieval batch
54    pub total: Duration,
55
56    /// Maximum time per individual retrieval
57    pub per_operation: Duration,
58
59    /// Maximum number of operations in this budget
60    pub max_operations: usize,
61}
62
63impl Default for LatencyBudget {
64    fn default() -> Self {
65        Self {
66            total: Duration::from_millis(50),
67            per_operation: Duration::from_millis(5),
68            max_operations: 10,
69        }
70    }
71}
72
73/// Tier statistics
74#[derive(Debug, Clone)]
75pub struct TierStats {
76    /// The tier
77    pub tier: Tier,
78
79    /// Number of points in this tier
80    pub count: usize,
81
82    /// Total size in bytes
83    pub size_bytes: usize,
84
85    /// Capacity in bytes
86    pub capacity_bytes: usize,
87
88    /// Usage ratio (0.0 to 1.0)
89    pub usage_ratio: f32,
90}
91
92/// Trait for latency measurement and adaptation
93///
94/// System adapters implement this trait.
95pub trait Latency: Send + Sync {
96    /// Probe a tier to measure current latency
97    ///
98    /// Performs a small test operation to measure actual latency.
99    fn probe(&mut self, tier: Tier) -> LatencyMeasurement;
100
101    /// Get the current latency budget
102    fn budget(&self) -> LatencyBudget;
103
104    /// Set a new latency budget
105    fn set_budget(&mut self, budget: LatencyBudget);
106
107    /// Get available capacity in a tier
108    fn available_capacity(&self, tier: Tier) -> usize;
109
110    /// Recommend which tier to use for an access pattern
111    ///
112    /// `expected_accesses` is the expected number of accesses for this data.
113    fn recommend_tier(&self, expected_accesses: u32) -> Tier;
114
115    /// Get statistics for a tier
116    fn tier_stats(&self, tier: Tier) -> TierStats;
117
118    /// Get statistics for all tiers
119    fn all_stats(&self) -> Vec<TierStats> {
120        vec![
121            self.tier_stats(Tier::Hot),
122            self.tier_stats(Tier::Warm),
123            self.tier_stats(Tier::Cold),
124        ]
125    }
126}