hyperstack_server/
config.rs

1use std::net::SocketAddr;
2use std::time::Duration;
3
4pub use crate::health::HealthConfig;
5pub use crate::http_health::HttpHealthConfig;
6
7/// Configuration for gRPC stream reconnection with exponential backoff
8#[derive(Clone, Debug)]
9pub struct ReconnectionConfig {
10    /// Initial delay before first reconnection attempt
11    pub initial_delay: Duration,
12    /// Maximum delay between reconnection attempts
13    pub max_delay: Duration,
14    /// Maximum number of reconnection attempts (None = infinite)
15    pub max_attempts: Option<u32>,
16    /// Multiplier for exponential backoff (typically 2.0)
17    pub backoff_multiplier: f64,
18    /// HTTP/2 keep-alive interval to prevent silent disconnects
19    pub http2_keep_alive_interval: Option<Duration>,
20}
21
22impl Default for ReconnectionConfig {
23    fn default() -> Self {
24        Self {
25            initial_delay: Duration::from_millis(100),
26            max_delay: Duration::from_secs(60),
27            max_attempts: None, // Infinite retries by default
28            backoff_multiplier: 2.0,
29            http2_keep_alive_interval: Some(Duration::from_secs(30)),
30        }
31    }
32}
33
34impl ReconnectionConfig {
35    pub fn new() -> Self {
36        Self::default()
37    }
38
39    pub fn with_initial_delay(mut self, delay: Duration) -> Self {
40        self.initial_delay = delay;
41        self
42    }
43
44    pub fn with_max_delay(mut self, delay: Duration) -> Self {
45        self.max_delay = delay;
46        self
47    }
48
49    pub fn with_max_attempts(mut self, attempts: u32) -> Self {
50        self.max_attempts = Some(attempts);
51        self
52    }
53
54    pub fn with_backoff_multiplier(mut self, multiplier: f64) -> Self {
55        self.backoff_multiplier = multiplier;
56        self
57    }
58
59    pub fn with_http2_keep_alive_interval(mut self, interval: Duration) -> Self {
60        self.http2_keep_alive_interval = Some(interval);
61        self
62    }
63
64    /// Calculate the next backoff duration given the current one
65    pub fn next_backoff(&self, current: Duration) -> Duration {
66        let next_secs = current.as_secs_f64() * self.backoff_multiplier;
67        let capped_secs = next_secs.min(self.max_delay.as_secs_f64());
68        Duration::from_secs_f64(capped_secs)
69    }
70}
71
72/// WebSocket server configuration
73#[derive(Clone, Debug)]
74pub struct WebSocketConfig {
75    pub bind_address: SocketAddr,
76}
77
78impl Default for WebSocketConfig {
79    fn default() -> Self {
80        Self {
81            bind_address: "[::]:8877".parse().expect("valid socket address"),
82        }
83    }
84}
85
86impl WebSocketConfig {
87    pub fn new(bind_address: impl Into<SocketAddr>) -> Self {
88        Self {
89            bind_address: bind_address.into(),
90        }
91    }
92}
93
94/// Yellowstone gRPC configuration
95#[derive(Clone, Debug)]
96pub struct YellowstoneConfig {
97    pub endpoint: String,
98    pub x_token: Option<String>,
99}
100
101impl YellowstoneConfig {
102    pub fn new(endpoint: impl Into<String>) -> Self {
103        Self {
104            endpoint: endpoint.into(),
105            x_token: None,
106        }
107    }
108
109    pub fn with_token(mut self, token: impl Into<String>) -> Self {
110        self.x_token = Some(token.into());
111        self
112    }
113}
114
115/// Main server configuration
116#[derive(Clone, Debug, Default)]
117pub struct ServerConfig {
118    pub websocket: Option<WebSocketConfig>,
119    pub yellowstone: Option<YellowstoneConfig>,
120    pub health: Option<HealthConfig>,
121    pub http_health: Option<HttpHealthConfig>,
122    pub reconnection: Option<ReconnectionConfig>,
123}
124
125impl ServerConfig {
126    pub fn new() -> Self {
127        Self::default()
128    }
129
130    pub fn with_websocket(mut self, config: WebSocketConfig) -> Self {
131        self.websocket = Some(config);
132        self
133    }
134
135    pub fn with_yellowstone(mut self, config: YellowstoneConfig) -> Self {
136        self.yellowstone = Some(config);
137        self
138    }
139
140    pub fn with_health(mut self, config: HealthConfig) -> Self {
141        self.health = Some(config);
142        self
143    }
144
145    pub fn with_http_health(mut self, config: HttpHealthConfig) -> Self {
146        self.http_health = Some(config);
147        self
148    }
149
150    pub fn with_reconnection(mut self, config: ReconnectionConfig) -> Self {
151        self.reconnection = Some(config);
152        self
153    }
154}