mockforge_grpc/reflection/mock_proxy/
proxy.rs1use crate::dynamic::ServiceRegistry;
6use crate::reflection::{
7 cache::DescriptorCache,
8 config::ProxyConfig,
9 connection_pool::ConnectionPool,
10 smart_mock_generator::{SmartMockConfig, SmartMockGenerator},
11};
12use std::sync::{
13 atomic::{AtomicUsize, Ordering},
14 Arc, Mutex,
15};
16use std::time::Duration;
17use tonic::Status;
18use tracing::debug;
19
20pub struct ConnectionGuard {
22 counter: Arc<AtomicUsize>,
23}
24
25impl Drop for ConnectionGuard {
26 fn drop(&mut self) {
27 self.counter.fetch_sub(1, Ordering::Relaxed);
28 }
29}
30
31pub struct MockReflectionProxy {
33 pub(crate) cache: DescriptorCache,
35 pub(crate) config: ProxyConfig,
37 pub(crate) timeout_duration: Duration,
39 #[allow(dead_code)]
41 pub(crate) connection_pool: ConnectionPool,
42 pub(crate) service_registry: Arc<ServiceRegistry>,
44 pub(crate) smart_generator: Arc<Mutex<SmartMockGenerator>>,
46 pub(crate) active_connections: Arc<AtomicUsize>,
48 pub(crate) total_requests: Arc<AtomicUsize>,
50}
51
52impl MockReflectionProxy {
53 pub async fn new(
55 config: ProxyConfig,
56 service_registry: Arc<ServiceRegistry>,
57 ) -> Result<Self, Status> {
58 debug!(
59 "Creating mock reflection proxy with {} services",
60 service_registry.service_names().len()
61 );
62
63 let cache = DescriptorCache::new();
64
65 cache.populate_from_pool(Some(service_registry.descriptor_pool())).await;
67
68 let connection_pool = ConnectionPool::new();
69
70 let timeout_duration = Duration::from_secs(config.request_timeout_seconds);
71
72 let smart_generator = Arc::new(Mutex::new(SmartMockGenerator::new(SmartMockConfig {
73 field_name_inference: true,
74 use_faker: true,
75 field_overrides: std::collections::HashMap::new(),
76 service_profiles: std::collections::HashMap::new(),
77 max_depth: 3,
78 seed: config.mock_seed,
79 deterministic: false,
80 })));
81
82 Ok(Self {
83 cache,
84 config,
85 timeout_duration,
86 connection_pool,
87 service_registry,
88 smart_generator,
89 active_connections: Arc::new(AtomicUsize::new(0)),
90 total_requests: Arc::new(AtomicUsize::new(0)),
91 })
92 }
93
94 pub fn config(&self) -> &ProxyConfig {
96 &self.config
97 }
98
99 pub fn cache(&self) -> &DescriptorCache {
101 &self.cache
102 }
103
104 pub fn service_registry(&self) -> &Arc<ServiceRegistry> {
106 &self.service_registry
107 }
108
109 pub fn service_names(&self) -> Vec<String> {
111 self.service_registry.service_names()
112 }
113
114 pub fn smart_generator(&self) -> &Arc<Mutex<SmartMockGenerator>> {
116 &self.smart_generator
117 }
118
119 pub fn should_mock_service_method(&self, service_name: &str, _method_name: &str) -> bool {
121 self.service_registry.get(service_name).is_some()
123 }
124
125 pub fn timeout_duration(&self) -> Duration {
127 self.timeout_duration
128 }
129
130 pub fn update_config(&mut self, config: ProxyConfig) {
132 self.config = config;
133 self.timeout_duration = Duration::from_secs(self.config.request_timeout_seconds);
135 }
136
137 pub fn track_connection(&self) -> ConnectionGuard {
139 self.active_connections.fetch_add(1, Ordering::Relaxed);
140 ConnectionGuard {
141 counter: self.active_connections.clone(),
142 }
143 }
144
145 pub async fn get_stats(&self) -> ProxyStats {
147 ProxyStats {
148 cached_services: self.cache.service_count().await,
149 cached_methods: self.cache.method_count().await,
150 registered_services: self.service_registry.service_names().len(),
151 total_requests: self.total_requests.load(Ordering::Relaxed) as u64,
152 active_connections: self.active_connections.load(Ordering::Relaxed),
153 }
154 }
155}
156
157#[derive(Debug, Clone)]
159pub struct ProxyStats {
160 pub cached_services: usize,
161 pub cached_methods: usize,
162 pub registered_services: usize,
163 pub total_requests: u64,
164 pub active_connections: usize,
165}
166
167impl Clone for MockReflectionProxy {
168 fn clone(&self) -> Self {
169 Self {
170 cache: self.cache.clone(),
171 config: self.config.clone(),
172 timeout_duration: self.timeout_duration,
173 connection_pool: self.connection_pool.clone(),
174 service_registry: self.service_registry.clone(),
175 smart_generator: self.smart_generator.clone(),
176 active_connections: self.active_connections.clone(),
177 total_requests: self.total_requests.clone(),
178 }
179 }
180}
181
182#[cfg(test)]
183mod tests {
184
185 #[test]
186 fn test_module_compiles() {}
187}