Skip to main content

oxirs_core/sla/
thresholds.rs

1//! SLA threshold parameters describing the resource budget of a single
2//! [`crate::sla::SlaClass`].
3
4use serde::{Deserialize, Serialize};
5
6/// Resource thresholds associated with an [`crate::sla::SlaClass`].
7///
8/// These thresholds describe the contract that a tenant signs onto when they
9/// receive a particular SLA tier.  They drive both:
10///
11/// * the token-bucket parameters of [`crate::sla::AdmissionController`], and
12/// * the latency / concurrency budgets enforced by downstream executors.
13#[derive(Debug, Clone, Serialize, Deserialize)]
14pub struct SlaThresholds {
15    /// p99 latency budget in milliseconds.
16    pub max_latency_p99_ms: u64,
17    /// Maximum simultaneous queries for a single tenant.
18    pub max_concurrent_queries: usize,
19    /// Maximum sustained bandwidth in MB/s.
20    pub bandwidth_mb_per_sec: f64,
21    /// Token-bucket refill rate (tokens/second).
22    pub token_refill_rate: f64,
23    /// Maximum token-bucket capacity (burst headroom).
24    pub token_bucket_capacity: f64,
25}
26
27#[cfg(test)]
28mod tests {
29    use super::*;
30
31    #[test]
32    fn test_thresholds_round_trip() {
33        let thresholds = SlaThresholds {
34            max_latency_p99_ms: 250,
35            max_concurrent_queries: 8,
36            bandwidth_mb_per_sec: 75.0,
37            token_refill_rate: 12.0,
38            token_bucket_capacity: 30.0,
39        };
40        let serialized = serde_json::to_string(&thresholds).expect("serialize");
41        let decoded: SlaThresholds = serde_json::from_str(&serialized).expect("deserialize");
42        assert_eq!(decoded.max_latency_p99_ms, thresholds.max_latency_p99_ms);
43        assert_eq!(
44            decoded.max_concurrent_queries,
45            thresholds.max_concurrent_queries
46        );
47        assert!((decoded.bandwidth_mb_per_sec - thresholds.bandwidth_mb_per_sec).abs() < 1e-9);
48        assert!((decoded.token_refill_rate - thresholds.token_refill_rate).abs() < 1e-9);
49        assert!((decoded.token_bucket_capacity - thresholds.token_bucket_capacity).abs() < 1e-9);
50    }
51}