d_engine/config/
network.rs

1use serde::Deserialize;
2use serde::Serialize;
3
4use crate::Error;
5use crate::Result;
6
7/// Network communication configuration for gRPC/HTTP2 transport
8///
9/// Provides fine-grained control over low-level network parameters
10#[derive(Debug, Serialize, Deserialize, Clone)]
11#[allow(unused)]
12pub struct NetworkConfig {
13    /// Timeout for establishing TCP connections in milliseconds
14    /// Default: 20ms (suitable for LAN environments)
15    #[serde(default = "default_connect_timeout")]
16    pub connect_timeout_in_ms: u64,
17
18    /// Maximum duration for completing gRPC requests in milliseconds
19    /// Default: 100ms (adjust based on RPC complexity)
20    #[serde(default = "default_request_timeout")]
21    pub request_timeout_in_ms: u64,
22
23    /// Maximum concurrent requests per connection
24    /// Default: 8192 (matches typical gRPC server settings)
25    #[serde(default = "default_concurrency_limit")]
26    pub concurrency_limit_per_connection: usize,
27
28    /// HTTP2 SETTINGS_MAX_CONCURRENT_STREAMS value
29    /// Default: 100 (controls concurrent streams per connection)
30    #[serde(default = "default_max_streams")]
31    pub max_concurrent_streams: u32,
32
33    /// Enable TCP_NODELAY to disable Nagle's algorithm
34    /// Default: true (recommended for low-latency scenarios)
35    #[serde(default = "default_tcp_nodelay")]
36    pub tcp_nodelay: bool,
37
38    /// TCP keepalive duration in seconds
39    /// Default: 3600s (1 hour, OS may enforce minimum values)
40    #[serde(default = "default_tcp_keepalive")]
41    pub tcp_keepalive_in_secs: u64,
42
43    /// HTTP2 keepalive ping interval in seconds
44    /// Default: 300s (5 minutes)
45    #[serde(default = "default_h2_keepalive_interval")]
46    pub http2_keep_alive_interval_in_secs: u64,
47
48    /// HTTP2 keepalive timeout in seconds
49    /// Default: 20s (must be < interval)
50    #[serde(default = "default_h2_keepalive_timeout")]
51    pub http2_keep_alive_timeout_in_secs: u64,
52
53    /// Maximum HTTP2 frame size in bytes
54    /// Default: 12MB (12582912 bytes)
55    #[serde(default = "default_max_frame_size")]
56    pub max_frame_size: u32,
57
58    /// Initial connection-level flow control window in bytes
59    /// Default: 12MB (12582912 bytes)
60    #[serde(default = "default_conn_window_size")]
61    pub initial_connection_window_size: u32,
62
63    /// Initial per-stream flow control window in bytes
64    /// Default: 2MB (2097152 bytes)
65    #[serde(default = "default_stream_window_size")]
66    pub initial_stream_window_size: u32,
67
68    /// I/O buffer size in bytes
69    /// Default: 64KB (65536 bytes)
70    #[serde(default = "default_buffer_size")]
71    pub buffer_size: usize,
72
73    /// Enable adaptive flow control window sizing
74    /// When enabled, overrides initial window size settings
75    /// Default: false (use fixed window sizes)
76    #[serde(default = "default_adaptive_window")]
77    pub http2_adaptive_window: bool,
78}
79
80impl Default for NetworkConfig {
81    fn default() -> Self {
82        Self {
83            connect_timeout_in_ms: default_connect_timeout(),
84            request_timeout_in_ms: default_request_timeout(),
85            concurrency_limit_per_connection: default_concurrency_limit(),
86            max_concurrent_streams: default_max_streams(),
87            tcp_nodelay: default_tcp_nodelay(),
88            http2_adaptive_window: default_adaptive_window(),
89            tcp_keepalive_in_secs: default_tcp_keepalive(),
90            http2_keep_alive_interval_in_secs: default_h2_keepalive_interval(),
91            http2_keep_alive_timeout_in_secs: default_h2_keepalive_timeout(),
92            max_frame_size: default_max_frame_size(),
93            initial_connection_window_size: default_conn_window_size(),
94            initial_stream_window_size: default_stream_window_size(),
95            buffer_size: default_buffer_size(),
96        }
97    }
98}
99impl NetworkConfig {
100    /// Validates network configuration consistency and safety
101    /// Returns Error::InvalidConfig with detailed message if any rule fails
102    pub fn validate(&self) -> Result<()> {
103        // 1. Validate timeouts
104        if self.connect_timeout_in_ms == 0 {
105            return Err(Error::InvalidConfig("Connection timeout must be greater than 0".into()));
106        }
107
108        if self.request_timeout_in_ms <= self.connect_timeout_in_ms {
109            return Err(Error::InvalidConfig(format!(
110                "Request timeout {}ms must exceed connection timeout {}ms",
111                self.request_timeout_in_ms, self.connect_timeout_in_ms
112            )));
113        }
114
115        // 2. Validate HTTP2 keepalive relationship
116        if self.http2_keep_alive_timeout_in_secs >= self.http2_keep_alive_interval_in_secs {
117            return Err(Error::InvalidConfig(format!(
118                "HTTP2 keepalive timeout {}s must be shorter than interval {}s",
119                self.http2_keep_alive_timeout_in_secs, self.http2_keep_alive_interval_in_secs
120            )));
121        }
122
123        // 3. Validate concurrency limits
124        if self.concurrency_limit_per_connection == 0 {
125            return Err(Error::InvalidConfig(
126                "Concurrency limit per connection must be > 0".into(),
127            ));
128        }
129
130        if self.max_concurrent_streams == 0 {
131            return Err(Error::InvalidConfig("Max concurrent streams must be > 0".into()));
132        }
133
134        // 4. Validate HTTP2 frame size limits
135        const MAX_FRAME_SIZE_LIMIT: u32 = 16_777_215; // 2^24-1 per spec
136        if self.max_frame_size > MAX_FRAME_SIZE_LIMIT {
137            return Err(Error::InvalidConfig(format!(
138                "Max frame size {} exceeds protocol limit {}",
139                self.max_frame_size, MAX_FRAME_SIZE_LIMIT
140            )));
141        }
142
143        // 5. Validate window sizes when adaptive window is disabled
144        if !self.http2_adaptive_window {
145            const MIN_INITIAL_WINDOW: u32 = 65_535; // HTTP2 minimum
146            if self.initial_stream_window_size < MIN_INITIAL_WINDOW {
147                return Err(Error::InvalidConfig(format!(
148                    "Initial stream window size {} below minimum {}",
149                    self.initial_stream_window_size, MIN_INITIAL_WINDOW
150                )));
151            }
152
153            if self.initial_connection_window_size < self.initial_stream_window_size {
154                return Err(Error::InvalidConfig(format!(
155                    "Connection window {} smaller than stream window {}",
156                    self.initial_connection_window_size, self.initial_stream_window_size
157                )));
158            }
159        }
160
161        // 6. Validate buffer sizing
162        if self.buffer_size < 1024 {
163            return Err(Error::InvalidConfig(format!(
164                "Buffer size {} too small, minimum 1024 bytes",
165                self.buffer_size
166            )));
167        }
168
169        Ok(())
170    }
171}
172
173// Default value implementations
174fn default_connect_timeout() -> u64 {
175    20
176}
177fn default_request_timeout() -> u64 {
178    100
179}
180fn default_concurrency_limit() -> usize {
181    8192
182}
183fn default_max_streams() -> u32 {
184    500
185}
186fn default_tcp_nodelay() -> bool {
187    true
188}
189fn default_tcp_keepalive() -> u64 {
190    3600
191}
192fn default_h2_keepalive_interval() -> u64 {
193    300
194}
195fn default_h2_keepalive_timeout() -> u64 {
196    20
197}
198fn default_max_frame_size() -> u32 {
199    16777215
200}
201fn default_conn_window_size() -> u32 {
202    12_582_912
203}
204fn default_stream_window_size() -> u32 {
205    2_097_152
206}
207fn default_buffer_size() -> usize {
208    65_536
209}
210fn default_adaptive_window() -> bool {
211    false
212}