heliosdb_proxy/routing/
mod.rs1pub mod hint_parser;
36pub mod query_router;
37pub mod node_filter;
38pub mod metrics;
39pub mod config;
40
41pub use hint_parser::{
42 HintParser, RoutingHint, RouteTarget, ConsistencyLevel,
43 QueryPriority, CacheBehavior, ParsedHints,
44};
45pub use query_router::{QueryRouter, RoutingDecision, RoutingReason};
46pub use node_filter::{NodeFilter, NodeCriteria, FilterResult, NodeInfo, NodeRole, SyncMode};
47pub use metrics::{RoutingMetrics, RoutingStats, HintUsageStats};
48pub use config::{RoutingConfig, HintConfig, ConsistencyConfig, AliasConfig};
49
50use thiserror::Error;
51use std::time::Duration;
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>().ok().map(|h| Duration::from_secs(h * 3600))
86 } else {
87 s.parse::<u64>().ok().map(Duration::from_millis)
89 }
90}
91
92#[cfg(test)]
93mod tests {
94 use super::*;
95
96 #[test]
97 fn test_parse_duration() {
98 assert_eq!(parse_duration("100ms"), Some(Duration::from_millis(100)));
99 assert_eq!(parse_duration("5s"), Some(Duration::from_secs(5)));
100 assert_eq!(parse_duration("2m"), Some(Duration::from_secs(120)));
101 assert_eq!(parse_duration("1h"), Some(Duration::from_secs(3600)));
102 assert_eq!(parse_duration("500"), Some(Duration::from_millis(500)));
103 assert_eq!(parse_duration("invalid"), None);
104 }
105}