1pub mod handler;
46pub mod service;
47pub mod streaming;
48
49pub use handler::{GrpcHandler, GrpcHandlerResult, GrpcRequestData, GrpcResponseData};
51pub use service::{GenericGrpcService, copy_metadata, is_grpc_request, parse_grpc_path};
52pub use streaming::{MessageStream, StreamingRequest, StreamingResponse};
53
54use serde::{Deserialize, Serialize};
55use std::collections::HashMap;
56use std::sync::Arc;
57
58#[derive(Debug, Clone, Serialize, Deserialize)]
63pub struct GrpcConfig {
64 #[serde(default = "default_true")]
66 pub enabled: bool,
67
68 #[serde(default = "default_max_message_size")]
70 pub max_message_size: usize,
71
72 #[serde(default = "default_true")]
74 pub enable_compression: bool,
75
76 #[serde(default)]
78 pub request_timeout: Option<u64>,
79
80 #[serde(default = "default_max_concurrent_streams")]
82 pub max_concurrent_streams: u32,
83
84 #[serde(default = "default_true")]
86 pub enable_keepalive: bool,
87
88 #[serde(default = "default_keepalive_interval")]
90 pub keepalive_interval: u64,
91
92 #[serde(default = "default_keepalive_timeout")]
94 pub keepalive_timeout: u64,
95}
96
97impl Default for GrpcConfig {
98 fn default() -> Self {
99 Self {
100 enabled: true,
101 max_message_size: default_max_message_size(),
102 enable_compression: true,
103 request_timeout: None,
104 max_concurrent_streams: default_max_concurrent_streams(),
105 enable_keepalive: true,
106 keepalive_interval: default_keepalive_interval(),
107 keepalive_timeout: default_keepalive_timeout(),
108 }
109 }
110}
111
112const fn default_true() -> bool {
113 true
114}
115
116const fn default_max_message_size() -> usize {
117 4 * 1024 * 1024 }
119
120const fn default_max_concurrent_streams() -> u32 {
121 100
122}
123
124const fn default_keepalive_interval() -> u64 {
125 75 }
127
128const fn default_keepalive_timeout() -> u64 {
129 20 }
131
132#[derive(Clone)]
148pub struct GrpcRegistry {
149 handlers: Arc<HashMap<String, Arc<dyn GrpcHandler>>>,
150}
151
152impl GrpcRegistry {
153 pub fn new() -> Self {
155 Self {
156 handlers: Arc::new(HashMap::new()),
157 }
158 }
159
160 pub fn register(&mut self, service_name: impl Into<String>, handler: Arc<dyn GrpcHandler>) {
167 let handlers = Arc::make_mut(&mut self.handlers);
168 handlers.insert(service_name.into(), handler);
169 }
170
171 pub fn get(&self, service_name: &str) -> Option<Arc<dyn GrpcHandler>> {
173 self.handlers.get(service_name).cloned()
174 }
175
176 pub fn service_names(&self) -> Vec<String> {
178 self.handlers.keys().cloned().collect()
179 }
180
181 pub fn contains(&self, service_name: &str) -> bool {
183 self.handlers.contains_key(service_name)
184 }
185
186 pub fn len(&self) -> usize {
188 self.handlers.len()
189 }
190
191 pub fn is_empty(&self) -> bool {
193 self.handlers.is_empty()
194 }
195}
196
197impl Default for GrpcRegistry {
198 fn default() -> Self {
199 Self::new()
200 }
201}
202
203#[cfg(test)]
204mod tests {
205 use super::*;
206 use crate::grpc::handler::{GrpcHandler, GrpcHandlerResult, GrpcRequestData};
207 use std::future::Future;
208 use std::pin::Pin;
209
210 struct TestHandler;
211
212 impl GrpcHandler for TestHandler {
213 fn call(&self, _request: GrpcRequestData) -> Pin<Box<dyn Future<Output = GrpcHandlerResult> + Send>> {
214 Box::pin(async {
215 Ok(GrpcResponseData {
216 payload: bytes::Bytes::new(),
217 metadata: tonic::metadata::MetadataMap::new(),
218 })
219 })
220 }
221
222 fn service_name(&self) -> &'static str {
223 "test.Service"
226 }
227 }
228
229 #[test]
230 fn test_grpc_config_default() {
231 let config = GrpcConfig::default();
232 assert!(config.enabled);
233 assert_eq!(config.max_message_size, 4 * 1024 * 1024);
234 assert!(config.enable_compression);
235 assert!(config.request_timeout.is_none());
236 assert_eq!(config.max_concurrent_streams, 100);
237 assert!(config.enable_keepalive);
238 assert_eq!(config.keepalive_interval, 75);
239 assert_eq!(config.keepalive_timeout, 20);
240 }
241
242 #[test]
243 fn test_grpc_config_serialization() {
244 let config = GrpcConfig::default();
245 let json = serde_json::to_string(&config).unwrap();
246 let deserialized: GrpcConfig = serde_json::from_str(&json).unwrap();
247
248 assert_eq!(config.enabled, deserialized.enabled);
249 assert_eq!(config.max_message_size, deserialized.max_message_size);
250 assert_eq!(config.enable_compression, deserialized.enable_compression);
251 }
252
253 #[test]
254 fn test_grpc_registry_new() {
255 let registry = GrpcRegistry::new();
256 assert!(registry.is_empty());
257 assert_eq!(registry.len(), 0);
258 }
259
260 #[test]
261 fn test_grpc_registry_register() {
262 let mut registry = GrpcRegistry::new();
263 let handler = Arc::new(TestHandler);
264
265 registry.register("test.Service", handler);
266
267 assert!(!registry.is_empty());
268 assert_eq!(registry.len(), 1);
269 assert!(registry.contains("test.Service"));
270 }
271
272 #[test]
273 fn test_grpc_registry_get() {
274 let mut registry = GrpcRegistry::new();
275 let handler = Arc::new(TestHandler);
276
277 registry.register("test.Service", handler);
278
279 let retrieved = registry.get("test.Service");
280 assert!(retrieved.is_some());
281 assert_eq!(retrieved.unwrap().service_name(), "test.Service");
282 }
283
284 #[test]
285 fn test_grpc_registry_get_nonexistent() {
286 let registry = GrpcRegistry::new();
287 let result = registry.get("nonexistent.Service");
288 assert!(result.is_none());
289 }
290
291 #[test]
292 fn test_grpc_registry_service_names() {
293 let mut registry = GrpcRegistry::new();
294
295 registry.register("service1", Arc::new(TestHandler));
296 registry.register("service2", Arc::new(TestHandler));
297 registry.register("service3", Arc::new(TestHandler));
298
299 let mut names = registry.service_names();
300 names.sort();
301
302 assert_eq!(names, vec!["service1", "service2", "service3"]);
303 }
304
305 #[test]
306 fn test_grpc_registry_contains() {
307 let mut registry = GrpcRegistry::new();
308 registry.register("test.Service", Arc::new(TestHandler));
309
310 assert!(registry.contains("test.Service"));
311 assert!(!registry.contains("other.Service"));
312 }
313
314 #[test]
315 fn test_grpc_registry_multiple_services() {
316 let mut registry = GrpcRegistry::new();
317
318 registry.register("user.Service", Arc::new(TestHandler));
319 registry.register("post.Service", Arc::new(TestHandler));
320
321 assert_eq!(registry.len(), 2);
322 assert!(registry.contains("user.Service"));
323 assert!(registry.contains("post.Service"));
324 }
325
326 #[test]
327 fn test_grpc_registry_clone() {
328 let mut registry = GrpcRegistry::new();
329 registry.register("test.Service", Arc::new(TestHandler));
330
331 let cloned = registry.clone();
332
333 assert_eq!(cloned.len(), 1);
334 assert!(cloned.contains("test.Service"));
335 }
336
337 #[test]
338 fn test_grpc_registry_default() {
339 let registry = GrpcRegistry::default();
340 assert!(registry.is_empty());
341 }
342}