1use crate::chaos_utilities::ChaosConfig;
10use crate::intelligent_behavior::config::IntelligentBehaviorConfig;
11use crate::latency::{LatencyDistribution, LatencyProfile};
12use serde::{Deserialize, Serialize};
13use std::sync::Arc;
14use tokio::sync::RwLock;
15
16#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
21#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
22#[serde(rename_all = "snake_case")]
23#[derive(Default)]
24pub enum RealityLevel {
25 StaticStubs = 1,
27 LightSimulation = 2,
29 #[default]
31 ModerateRealism = 3,
32 HighRealism = 4,
34 ProductionChaos = 5,
36}
37
38impl RealityLevel {
39 pub fn value(&self) -> u8 {
41 *self as u8
42 }
43
44 pub fn name(&self) -> &'static str {
46 match self {
47 RealityLevel::StaticStubs => "Static Stubs",
48 RealityLevel::LightSimulation => "Light Simulation",
49 RealityLevel::ModerateRealism => "Moderate Realism",
50 RealityLevel::HighRealism => "High Realism",
51 RealityLevel::ProductionChaos => "Production Chaos",
52 }
53 }
54
55 pub fn description(&self) -> &'static str {
57 match self {
58 RealityLevel::StaticStubs => "Simple, instant responses with no chaos",
59 RealityLevel::LightSimulation => "Minimal latency, basic intelligence",
60 RealityLevel::ModerateRealism => "Some chaos, moderate latency, full intelligence",
61 RealityLevel::HighRealism => "Increased chaos, realistic latency, session state",
62 RealityLevel::ProductionChaos => {
63 "Maximum chaos, production-like latency, full features"
64 }
65 }
66 }
67
68 pub fn from_value(value: u8) -> Option<Self> {
70 match value {
71 1 => Some(RealityLevel::StaticStubs),
72 2 => Some(RealityLevel::LightSimulation),
73 3 => Some(RealityLevel::ModerateRealism),
74 4 => Some(RealityLevel::HighRealism),
75 5 => Some(RealityLevel::ProductionChaos),
76 _ => None,
77 }
78 }
79
80 pub fn all() -> Vec<Self> {
82 vec![
83 RealityLevel::StaticStubs,
84 RealityLevel::LightSimulation,
85 RealityLevel::ModerateRealism,
86 RealityLevel::HighRealism,
87 RealityLevel::ProductionChaos,
88 ]
89 }
90}
91
92#[derive(Debug, Clone, Serialize, Deserialize)]
94pub struct RealityConfig {
95 pub level: RealityLevel,
97 pub chaos: ChaosConfig,
99 pub latency: LatencyProfile,
101 pub mockai: IntelligentBehaviorConfig,
103}
104
105impl RealityConfig {
106 pub fn for_level(level: RealityLevel) -> Self {
108 match level {
109 RealityLevel::StaticStubs => Self::level_1_static_stubs(),
110 RealityLevel::LightSimulation => Self::level_2_light_simulation(),
111 RealityLevel::ModerateRealism => Self::level_3_moderate_realism(),
112 RealityLevel::HighRealism => Self::level_4_high_realism(),
113 RealityLevel::ProductionChaos => Self::level_5_production_chaos(),
114 }
115 }
116
117 fn level_1_static_stubs() -> Self {
123 Self {
124 level: RealityLevel::StaticStubs,
125 chaos: ChaosConfig {
126 enabled: false,
127 error_rate: 0.0,
128 delay_rate: 0.0,
129 min_delay_ms: 0,
130 max_delay_ms: 0,
131 status_codes: vec![],
132 inject_timeouts: false,
133 timeout_ms: 0,
134 },
135 latency: LatencyProfile {
136 base_ms: 0,
137 jitter_ms: 0,
138 distribution: LatencyDistribution::Fixed,
139 std_dev_ms: None,
140 pareto_shape: None,
141 min_ms: 0,
142 max_ms: Some(0),
143 tag_overrides: Default::default(),
144 },
145 mockai: IntelligentBehaviorConfig {
146 enabled: false,
147 ..Default::default()
148 },
149 }
150 }
151
152 fn level_2_light_simulation() -> Self {
158 Self {
159 level: RealityLevel::LightSimulation,
160 chaos: ChaosConfig {
161 enabled: false,
162 error_rate: 0.0,
163 delay_rate: 0.0,
164 min_delay_ms: 0,
165 max_delay_ms: 0,
166 status_codes: vec![],
167 inject_timeouts: false,
168 timeout_ms: 0,
169 },
170 latency: LatencyProfile {
171 base_ms: 30,
172 jitter_ms: 20,
173 distribution: LatencyDistribution::Fixed,
174 std_dev_ms: None,
175 pareto_shape: None,
176 min_ms: 10,
177 max_ms: Some(50),
178 tag_overrides: Default::default(),
179 },
180 mockai: IntelligentBehaviorConfig {
181 enabled: true,
182 ..Default::default()
183 },
184 }
185 }
186
187 fn level_3_moderate_realism() -> Self {
193 Self {
194 level: RealityLevel::ModerateRealism,
195 chaos: ChaosConfig {
196 enabled: true,
197 error_rate: 0.05,
198 delay_rate: 0.10,
199 min_delay_ms: 50,
200 max_delay_ms: 200,
201 status_codes: vec![500, 502, 503],
202 inject_timeouts: false,
203 timeout_ms: 0,
204 },
205 latency: LatencyProfile {
206 base_ms: 125,
207 jitter_ms: 75,
208 distribution: LatencyDistribution::Normal,
209 std_dev_ms: Some(30.0),
210 pareto_shape: None,
211 min_ms: 50,
212 max_ms: Some(200),
213 tag_overrides: Default::default(),
214 },
215 mockai: IntelligentBehaviorConfig {
216 enabled: true,
217 ..Default::default()
218 },
219 }
220 }
221
222 fn level_4_high_realism() -> Self {
228 Self {
229 level: RealityLevel::HighRealism,
230 chaos: ChaosConfig {
231 enabled: true,
232 error_rate: 0.10,
233 delay_rate: 0.20,
234 min_delay_ms: 100,
235 max_delay_ms: 500,
236 status_codes: vec![500, 502, 503, 504],
237 inject_timeouts: false,
238 timeout_ms: 0,
239 },
240 latency: LatencyProfile {
241 base_ms: 300,
242 jitter_ms: 200,
243 distribution: LatencyDistribution::Normal,
244 std_dev_ms: Some(80.0),
245 pareto_shape: None,
246 min_ms: 100,
247 max_ms: Some(500),
248 tag_overrides: Default::default(),
249 },
250 mockai: IntelligentBehaviorConfig {
251 enabled: true,
252 performance: crate::intelligent_behavior::config::PerformanceConfig {
253 max_history_length: 100,
254 session_timeout_seconds: 3600,
255 ..Default::default()
256 },
257 ..Default::default()
258 },
259 }
260 }
261
262 fn level_5_production_chaos() -> Self {
268 Self {
269 level: RealityLevel::ProductionChaos,
270 chaos: ChaosConfig {
271 enabled: true,
272 error_rate: 0.15,
273 delay_rate: 0.30,
274 min_delay_ms: 200,
275 max_delay_ms: 2000,
276 status_codes: vec![500, 502, 503, 504, 408],
277 inject_timeouts: true,
278 timeout_ms: 5000,
279 },
280 latency: LatencyProfile {
281 base_ms: 1100,
282 jitter_ms: 900,
283 distribution: LatencyDistribution::Pareto,
284 std_dev_ms: None,
285 pareto_shape: Some(2.0),
286 min_ms: 200,
287 max_ms: Some(2000),
288 tag_overrides: Default::default(),
289 },
290 mockai: IntelligentBehaviorConfig {
291 enabled: true,
292 performance: crate::intelligent_behavior::config::PerformanceConfig {
293 max_history_length: 200,
294 session_timeout_seconds: 7200,
295 ..Default::default()
296 },
297 ..Default::default()
298 },
299 }
300 }
301}
302
303impl Default for RealityConfig {
304 fn default() -> Self {
305 Self::for_level(RealityLevel::default())
306 }
307}
308
309#[derive(Debug, Clone, Serialize, Deserialize)]
311pub struct RealityPreset {
312 pub name: String,
314 pub description: Option<String>,
316 pub config: RealityConfig,
318 pub metadata: Option<PresetMetadata>,
320}
321
322#[derive(Debug, Clone, Serialize, Deserialize)]
324pub struct PresetMetadata {
325 pub created_at: Option<String>,
327 pub author: Option<String>,
329 pub tags: Vec<String>,
331 pub version: Option<String>,
333}
334
335impl Default for PresetMetadata {
336 fn default() -> Self {
337 Self {
338 created_at: None,
339 author: None,
340 tags: vec![],
341 version: Some("1.0".to_string()),
342 }
343 }
344}
345
346#[derive(Debug, Clone)]
352pub struct RealityEngine {
353 config: Arc<RwLock<RealityConfig>>,
355}
356
357impl RealityEngine {
358 pub fn new() -> Self {
360 Self {
361 config: Arc::new(RwLock::new(RealityConfig::default())),
362 }
363 }
364
365 pub fn with_level(level: RealityLevel) -> Self {
367 Self {
368 config: Arc::new(RwLock::new(RealityConfig::for_level(level))),
369 }
370 }
371
372 pub async fn get_level(&self) -> RealityLevel {
374 self.config.read().await.level
375 }
376
377 pub async fn set_level(&self, level: RealityLevel) {
379 let mut config = self.config.write().await;
380 *config = RealityConfig::for_level(level);
381 }
382
383 pub async fn get_config(&self) -> RealityConfig {
385 self.config.read().await.clone()
386 }
387
388 pub async fn get_chaos_config(&self) -> ChaosConfig {
390 self.config.read().await.chaos.clone()
391 }
392
393 pub async fn get_latency_profile(&self) -> LatencyProfile {
395 self.config.read().await.latency.clone()
396 }
397
398 pub async fn get_mockai_config(&self) -> IntelligentBehaviorConfig {
400 self.config.read().await.mockai.clone()
401 }
402
403 pub async fn create_preset(&self, name: String, description: Option<String>) -> RealityPreset {
405 let config = self.config.read().await.clone();
406 RealityPreset {
407 name,
408 description,
409 config,
410 metadata: Some(PresetMetadata {
411 created_at: Some(chrono::Utc::now().to_rfc3339()),
412 author: None,
413 tags: vec![],
414 version: Some("1.0".to_string()),
415 }),
416 }
417 }
418
419 pub async fn apply_preset(&self, preset: RealityPreset) {
421 let mut config = self.config.write().await;
422 *config = preset.config;
423 }
424
425 pub async fn apply_to_config(&self, config: &mut crate::config::ServerConfig) {
431 let reality_config = self.get_config().await;
432
433 if config.reality.enabled {
435 if let Some(ref mut chaos_eng) = config.observability.chaos {
437 chaos_eng.enabled = reality_config.chaos.enabled;
438 if let Some(ref mut fault) = chaos_eng.fault_injection {
439 fault.enabled = reality_config.chaos.enabled;
440 fault.http_error_probability = reality_config.chaos.error_rate;
441 fault.timeout_errors = reality_config.chaos.inject_timeouts;
442 fault.timeout_ms = reality_config.chaos.timeout_ms;
443 }
444 if let Some(ref mut latency) = chaos_eng.latency {
445 latency.enabled = reality_config.latency.base_ms > 0;
446 latency.fixed_delay_ms = Some(reality_config.latency.base_ms);
447 latency.jitter_percent = if reality_config.latency.jitter_ms > 0 {
448 (reality_config.latency.jitter_ms as f64
449 / reality_config.latency.base_ms as f64)
450 .min(1.0)
451 } else {
452 0.0
453 };
454 }
455 }
456 }
457
458 if config.reality.enabled {
460 config.core.default_latency = reality_config.latency.clone();
461 config.core.latency_enabled = reality_config.latency.base_ms > 0;
462 }
463
464 if config.reality.enabled {
466 config.mockai.enabled = reality_config.mockai.enabled;
467 config.mockai.intelligent_behavior = reality_config.mockai.clone();
468 }
469 }
470}
471
472impl Default for RealityEngine {
473 fn default() -> Self {
474 Self::new()
475 }
476}
477
478#[cfg(test)]
479mod tests {
480 use super::*;
481
482 #[test]
483 fn test_reality_level_values() {
484 assert_eq!(RealityLevel::StaticStubs.value(), 1);
485 assert_eq!(RealityLevel::LightSimulation.value(), 2);
486 assert_eq!(RealityLevel::ModerateRealism.value(), 3);
487 assert_eq!(RealityLevel::HighRealism.value(), 4);
488 assert_eq!(RealityLevel::ProductionChaos.value(), 5);
489 }
490
491 #[test]
492 fn test_reality_level_from_value() {
493 assert_eq!(RealityLevel::from_value(1), Some(RealityLevel::StaticStubs));
494 assert_eq!(RealityLevel::from_value(3), Some(RealityLevel::ModerateRealism));
495 assert_eq!(RealityLevel::from_value(5), Some(RealityLevel::ProductionChaos));
496 assert_eq!(RealityLevel::from_value(0), None);
497 assert_eq!(RealityLevel::from_value(6), None);
498 }
499
500 #[test]
501 fn test_level_1_config() {
502 let config = RealityConfig::for_level(RealityLevel::StaticStubs);
503 assert!(!config.chaos.enabled);
504 assert_eq!(config.latency.base_ms, 0);
505 assert!(!config.mockai.enabled);
506 }
507
508 #[test]
509 fn test_level_5_config() {
510 let config = RealityConfig::for_level(RealityLevel::ProductionChaos);
511 assert!(config.chaos.enabled);
512 assert!(config.chaos.inject_timeouts);
513 assert_eq!(config.chaos.error_rate, 0.15);
514 assert!(config.latency.base_ms >= 200);
515 assert!(config.mockai.enabled);
516 }
517
518 #[tokio::test]
519 async fn test_reality_engine() {
520 let engine = RealityEngine::with_level(RealityLevel::StaticStubs);
521 assert_eq!(engine.get_level().await, RealityLevel::StaticStubs);
522
523 engine.set_level(RealityLevel::ProductionChaos).await;
524 assert_eq!(engine.get_level().await, RealityLevel::ProductionChaos);
525
526 let chaos_config = engine.get_chaos_config().await;
527 assert!(chaos_config.enabled);
528 }
529
530 #[tokio::test]
531 async fn test_preset_creation() {
532 let engine = RealityEngine::with_level(RealityLevel::ModerateRealism);
533 let preset = engine
534 .create_preset("test-preset".to_string(), Some("Test description".to_string()))
535 .await;
536
537 assert_eq!(preset.name, "test-preset");
538 assert_eq!(preset.config.level, RealityLevel::ModerateRealism);
539 assert!(preset.metadata.is_some());
540 }
541}