heliosdb_proxy/routing/
mod.rs1pub mod config;
36pub mod hint_parser;
37pub mod metrics;
38pub mod node_filter;
39pub mod query_router;
40
41pub use config::{AliasConfig, ConsistencyConfig, HintConfig, RoutingConfig};
42pub use hint_parser::{
43 CacheBehavior, ConsistencyLevel, HintParser, ParsedHints, QueryPriority, RouteTarget,
44 RoutingHint,
45};
46pub use metrics::{HintUsageStats, RoutingMetrics, RoutingStats};
47pub use node_filter::{FilterResult, NodeCriteria, NodeFilter, NodeInfo, NodeRole, SyncMode};
48pub use query_router::{QueryRouter, RoutingDecision, RoutingReason};
49
50use std::time::Duration;
51use thiserror::Error;
52
53#[derive(Debug, Error)]
55pub enum RoutingError {
56 #[error("No nodes match routing hints: {0}")]
57 NoMatchingNodes(String),
58
59 #[error("Invalid hint combination: {0}")]
60 InvalidHintCombination(String),
61
62 #[error("Node not found: {0}")]
63 NodeNotFound(String),
64
65 #[error("Hint not allowed: {0}")]
66 HintNotAllowed(String),
67
68 #[error("Parse error: {0}")]
69 ParseError(String),
70}
71
72pub type Result<T> = std::result::Result<T, RoutingError>;
73
74pub fn parse_duration(s: &str) -> Option<Duration> {
76 let s = s.trim().to_lowercase();
77
78 if let Some(num) = s.strip_suffix("ms") {
79 num.parse::<u64>().ok().map(Duration::from_millis)
80 } else if let Some(num) = s.strip_suffix('s') {
81 num.parse::<u64>().ok().map(Duration::from_secs)
82 } else if let Some(num) = s.strip_suffix('m') {
83 num.parse::<u64>().ok().map(|m| Duration::from_secs(m * 60))
84 } else if let Some(num) = s.strip_suffix('h') {
85 num.parse::<u64>()
86 .ok()
87 .map(|h| Duration::from_secs(h * 3600))
88 } else {
89 s.parse::<u64>().ok().map(Duration::from_millis)
91 }
92}
93
94#[cfg(test)]
95mod tests {
96 use super::*;
97
98 #[test]
99 fn test_parse_duration() {
100 assert_eq!(parse_duration("100ms"), Some(Duration::from_millis(100)));
101 assert_eq!(parse_duration("5s"), Some(Duration::from_secs(5)));
102 assert_eq!(parse_duration("2m"), Some(Duration::from_secs(120)));
103 assert_eq!(parse_duration("1h"), Some(Duration::from_secs(3600)));
104 assert_eq!(parse_duration("500"), Some(Duration::from_millis(500)));
105 assert_eq!(parse_duration("invalid"), None);
106 }
107}