1use sklears_core::error::{Result as SklResult, SklearsError};
155use std::collections::HashMap;
156use std::time::Duration;
157
158#[derive(Debug, Clone)]
160pub struct ExecutionEngineConfig {
161 pub name: String,
163 pub default_strategy: String,
165 pub resource_constraints: ResourceConstraints,
167 pub performance_goals: PerformanceGoals,
169 pub energy_efficiency: EnergyEfficiencyGoal,
171 pub fault_tolerance: FaultToleranceConfig,
173 pub monitoring: MonitoringConfig,
175 pub io_limits: IoLimits,
177}
178
179#[derive(Debug, Clone)]
181pub struct ResourceConstraints {
182 pub max_cpu_cores: Option<usize>,
183 pub max_memory: Option<u64>,
184 pub max_gpu_devices: Option<usize>,
185 pub max_concurrent_tasks: Option<usize>,
186 pub max_task_time: Option<Duration>,
187 pub memory_limit_per_task: Option<u64>,
188 pub cpu_quota_per_task: Option<f64>,
189 pub gpu_memory_per_task: Option<u64>,
190 pub network_bandwidth_per_task: Option<u64>,
191 pub max_queue_depth: Option<usize>,
192 pub priority_levels: Option<u8>,
193 pub isolation_mode: ResourceIsolationMode,
194}
195
196#[derive(Debug, Clone, PartialEq)]
198pub enum ResourceIsolationMode {
199 None,
201 Soft,
203 Hard,
205 Container,
207 VirtualMachine,
209}
210
211#[derive(Debug, Clone)]
213pub struct PerformanceGoals {
214 pub target_throughput: Option<f64>,
216 pub target_latency: Option<f64>,
218 pub target_utilization: Option<f64>,
220 pub target_efficiency: Option<f64>,
222 pub target_cache_hit_ratio: Option<f64>,
224 pub target_memory_bandwidth: Option<f64>,
226 pub target_cpu_frequency: Option<f64>,
228 pub optimization_mode: PerformanceMode,
230 pub qos_level: QualityOfService,
232}
233
234#[derive(Debug, Clone, PartialEq)]
236pub enum PerformanceMode {
237 Throughput,
239 Latency,
241 Balanced,
243 EnergyEfficient,
245 CostOptimized,
247 Custom(String),
249}
250
251#[derive(Debug, Clone, PartialEq)]
253pub enum QualityOfService {
254 BestEffort,
256 Guaranteed,
258 Burstable { baseline: f64 },
260 RealTime { deadline: Duration },
262}
263
264#[derive(Debug, Clone)]
266pub struct EnergyEfficiencyGoal {
267 pub target_power_consumption: Option<f64>,
269 pub enable_power_capping: bool,
271 pub dynamic_frequency_scaling: bool,
273 pub energy_aware_scheduling: bool,
275 pub thermal_throttling: bool,
277 pub target_temperature: Option<f64>,
279 pub power_mode: PowerMode,
281 pub carbon_awareness: CarbonAwareness,
283}
284
285#[derive(Debug, Clone, PartialEq)]
287pub enum PowerMode {
288 PerformanceFirst,
290 Balanced,
292 PowerSaver,
294 EcoMode,
296 Custom {
298 max_watts: f64,
299 efficiency_target: f64,
300 },
301}
302
303#[derive(Debug, Clone, Default)]
305pub struct CarbonAwareness {
306 pub enabled: bool,
308 pub prefer_renewable: bool,
310 pub carbon_intensity_threshold: Option<f64>,
312 pub time_of_use_optimization: bool,
314}
315
316#[derive(Debug, Clone)]
318pub struct FaultToleranceConfig {
319 pub enable_retry: bool,
320 pub max_retries: u32,
321 pub backoff_strategy: BackoffStrategy,
322 pub enable_circuit_breaker: bool,
323 pub circuit_breaker_threshold: u32,
324 pub circuit_breaker_timeout: Duration,
325 pub enable_failover: bool,
326 pub failover_targets: Vec<String>,
327 pub health_check: HealthCheckConfig,
328 pub enable_graceful_degradation: bool,
329 pub failure_detection: FailureDetectionStrategy,
330 pub recovery_strategy: RecoveryStrategy,
331}
332
333#[derive(Debug, Clone)]
335pub enum BackoffStrategy {
336 Fixed { delay: Duration },
338 Linear { delay: Duration },
340 Exponential {
342 base_delay: Duration,
343 max_delay: Duration,
344 },
345 ExponentialWithJitter {
347 base_delay: Duration,
348 max_delay: Duration,
349 jitter_factor: f64,
350 },
351 Custom(fn(u32) -> Duration),
353}
354
355#[derive(Debug, Clone)]
357pub struct HealthCheckConfig {
358 pub enabled: bool,
360 pub interval: Duration,
362 pub timeout: Duration,
364 pub failure_threshold: u32,
366 pub recovery_threshold: u32,
368 pub endpoints: Vec<HealthCheckEndpoint>,
370 pub custom_checks: Vec<String>,
372}
373
374#[derive(Debug, Clone)]
376pub struct HealthCheckEndpoint {
377 pub name: String,
379 pub url: String,
381 pub method: String,
383 pub expected_status: u16,
385 pub timeout: Duration,
387}
388
389#[derive(Debug, Clone, PartialEq)]
391pub enum FailureDetectionStrategy {
392 Timeout,
394 Heartbeat { interval: Duration },
396 PerformanceDegradation { threshold: f64 },
398 ResourceExhaustion,
400 MultiCriteria(Vec<FailureDetectionStrategy>),
402}
403
404#[derive(Debug, Clone, PartialEq)]
406pub enum RecoveryStrategy {
407 Restart,
409 Failover,
411 GracefulDegradation,
413 Manual,
415 Custom(String),
417}
418
419#[derive(Debug, Clone)]
421pub struct MonitoringConfig {
422 pub collection_interval: Duration,
424 pub enable_detailed_metrics: bool,
426 pub enable_distributed_tracing: bool,
428 pub enable_profiling: bool,
430 pub enable_debug_logging: bool,
432 pub export_prometheus: bool,
434 pub export_jaeger: bool,
436 pub export_influxdb: bool,
438 pub custom_metrics: Vec<String>,
440 pub alerting: AlertingConfig,
442 pub sampling_config: SamplingConfig,
444}
445
446#[derive(Debug, Clone)]
448pub struct AlertingConfig {
449 pub enabled: bool,
451 pub channels: Vec<AlertChannel>,
453 pub rules: Vec<AlertRule>,
455 pub aggregation_window: Duration,
457 pub rate_limit: AlertRateLimit,
459}
460
461#[derive(Debug, Clone)]
463pub struct AlertChannel {
464 pub channel_type: String,
466 pub config: HashMap<String, String>,
468 pub priority: AlertPriority,
470}
471
472#[derive(Debug, Clone)]
474pub struct AlertRule {
475 pub name: String,
477 pub metric: String,
479 pub threshold: f64,
481 pub operator: ComparisonOperator,
483 pub severity: AlertSeverity,
485 pub message_template: String,
487}
488
489#[derive(Debug, Clone, PartialEq)]
491pub enum AlertPriority {
492 Low,
494 Medium,
496 High,
498 Critical,
500}
501
502#[derive(Debug, Clone, PartialEq)]
504pub enum AlertSeverity {
505 Info,
507 Warning,
509 Error,
511 Critical,
513}
514
515#[derive(Debug, Clone, PartialEq)]
517pub enum ComparisonOperator {
518 Greater,
520 GreaterEqual,
522 Less,
524 LessEqual,
526 Equal,
528 NotEqual,
530}
531
532#[derive(Debug, Clone)]
534pub struct AlertRateLimit {
535 pub max_alerts: u32,
537 pub time_window: Duration,
539 pub burst_allowance: u32,
541}
542
543#[derive(Debug, Clone)]
545pub struct SamplingConfig {
546 pub sampling_rate: f64,
548 pub adaptive_sampling: bool,
550 pub min_samples_per_second: u32,
552 pub max_samples_per_second: u32,
554}
555
556#[derive(Debug, Clone)]
558pub struct IoLimits {
559 pub max_read_bandwidth: Option<u64>,
561 pub max_write_bandwidth: Option<u64>,
563 pub max_iops: Option<u64>,
565 pub max_concurrent_io: Option<usize>,
567 pub io_priority: IoPriority,
569 pub io_scheduler: IoScheduler,
571 pub buffer_size: Option<usize>,
573 pub direct_io: bool,
575 pub compression: IoCompression,
577}
578
579#[derive(Debug, Clone, PartialEq)]
581pub enum IoPriority {
582 Low,
584 Normal,
586 High,
588 RealTime,
590}
591
592#[derive(Debug, Clone, PartialEq)]
594pub enum IoScheduler {
595 CFQ,
597 Deadline,
599 Noop,
601 BFQ,
603 MQ,
605}
606
607#[derive(Debug, Clone)]
609pub struct IoCompression {
610 pub enabled: bool,
612 pub algorithm: CompressionAlgorithm,
614 pub level: u8,
616 pub threshold: usize,
618}
619
620#[derive(Debug, Clone, PartialEq)]
622pub enum CompressionAlgorithm {
623 Gzip,
625 Lz4,
627 Zstd,
629 Snappy,
631 Brotli,
633}
634
635impl Default for ExecutionEngineConfig {
637 fn default() -> Self {
638 Self {
639 name: "default_engine".to_string(),
640 default_strategy: "sequential".to_string(),
641 resource_constraints: ResourceConstraints::default(),
642 performance_goals: PerformanceGoals::default(),
643 energy_efficiency: EnergyEfficiencyGoal::default(),
644 fault_tolerance: FaultToleranceConfig::default(),
645 monitoring: MonitoringConfig::default(),
646 io_limits: IoLimits::default(),
647 }
648 }
649}
650
651impl Default for ResourceConstraints {
652 fn default() -> Self {
653 Self {
654 max_cpu_cores: None,
655 max_memory: None,
656 max_gpu_devices: None,
657 max_concurrent_tasks: Some(100),
658 max_task_time: Some(Duration::from_secs(3600)), memory_limit_per_task: None,
660 cpu_quota_per_task: None,
661 gpu_memory_per_task: None,
662 network_bandwidth_per_task: None,
663 max_queue_depth: Some(1000),
664 priority_levels: Some(3),
665 isolation_mode: ResourceIsolationMode::Soft,
666 }
667 }
668}
669
670impl Default for PerformanceGoals {
671 fn default() -> Self {
672 Self {
673 target_throughput: None,
674 target_latency: None,
675 target_utilization: Some(80.0), target_efficiency: Some(90.0), target_cache_hit_ratio: Some(0.8), target_memory_bandwidth: None,
679 target_cpu_frequency: None,
680 optimization_mode: PerformanceMode::Balanced,
681 qos_level: QualityOfService::BestEffort,
682 }
683 }
684}
685
686impl Default for EnergyEfficiencyGoal {
687 fn default() -> Self {
688 Self {
689 target_power_consumption: None,
690 enable_power_capping: false,
691 dynamic_frequency_scaling: true,
692 energy_aware_scheduling: false,
693 thermal_throttling: true,
694 target_temperature: Some(75.0), power_mode: PowerMode::Balanced,
696 carbon_awareness: CarbonAwareness::default(),
697 }
698 }
699}
700
701impl Default for FaultToleranceConfig {
702 fn default() -> Self {
703 Self {
704 enable_retry: true,
705 max_retries: 3,
706 backoff_strategy: BackoffStrategy::Exponential {
707 base_delay: Duration::from_millis(100),
708 max_delay: Duration::from_secs(30),
709 },
710 enable_circuit_breaker: false,
711 circuit_breaker_threshold: 10,
712 circuit_breaker_timeout: Duration::from_secs(60),
713 enable_failover: false,
714 failover_targets: Vec::new(),
715 health_check: HealthCheckConfig::default(),
716 enable_graceful_degradation: true,
717 failure_detection: FailureDetectionStrategy::Timeout,
718 recovery_strategy: RecoveryStrategy::Restart,
719 }
720 }
721}
722
723impl Default for HealthCheckConfig {
724 fn default() -> Self {
725 Self {
726 enabled: true,
727 interval: Duration::from_secs(30),
728 timeout: Duration::from_secs(5),
729 failure_threshold: 3,
730 recovery_threshold: 2,
731 endpoints: Vec::new(),
732 custom_checks: Vec::new(),
733 }
734 }
735}
736
737impl Default for MonitoringConfig {
738 fn default() -> Self {
739 Self {
740 collection_interval: Duration::from_secs(10),
741 enable_detailed_metrics: false,
742 enable_distributed_tracing: false,
743 enable_profiling: false,
744 enable_debug_logging: false,
745 export_prometheus: false,
746 export_jaeger: false,
747 export_influxdb: false,
748 custom_metrics: Vec::new(),
749 alerting: AlertingConfig::default(),
750 sampling_config: SamplingConfig::default(),
751 }
752 }
753}
754
755impl Default for AlertingConfig {
756 fn default() -> Self {
757 Self {
758 enabled: false,
759 channels: Vec::new(),
760 rules: Vec::new(),
761 aggregation_window: Duration::from_secs(60),
762 rate_limit: AlertRateLimit::default(),
763 }
764 }
765}
766
767impl Default for AlertRateLimit {
768 fn default() -> Self {
769 Self {
770 max_alerts: 10,
771 time_window: Duration::from_secs(300), burst_allowance: 3,
773 }
774 }
775}
776
777impl Default for SamplingConfig {
778 fn default() -> Self {
779 Self {
780 sampling_rate: 0.1, adaptive_sampling: false,
782 min_samples_per_second: 1,
783 max_samples_per_second: 100,
784 }
785 }
786}
787
788impl Default for IoLimits {
789 fn default() -> Self {
790 Self {
791 max_read_bandwidth: None,
792 max_write_bandwidth: None,
793 max_iops: None,
794 max_concurrent_io: Some(100),
795 io_priority: IoPriority::Normal,
796 io_scheduler: IoScheduler::CFQ,
797 buffer_size: Some(64 * 1024), direct_io: false,
799 compression: IoCompression::default(),
800 }
801 }
802}
803
804impl Default for IoCompression {
805 fn default() -> Self {
806 Self {
807 enabled: false,
808 algorithm: CompressionAlgorithm::Lz4,
809 level: 6,
810 threshold: 1024, }
812 }
813}
814
815pub type DefaultExecutionEngineConfig = ExecutionEngineConfig;
817
818impl ExecutionEngineConfig {
820 pub fn validate(&self) -> SklResult<()> {
822 self.resource_constraints.validate()?;
824
825 self.performance_goals.validate()?;
827
828 self.fault_tolerance.validate()?;
830
831 self.monitoring.validate()?;
833
834 self.io_limits.validate()?;
836
837 Ok(())
838 }
839}
840
841impl ResourceConstraints {
842 pub fn validate(&self) -> SklResult<()> {
843 if let Some(cores) = self.max_cpu_cores {
844 if cores == 0 {
845 return Err(SklearsError::InvalidInput(
846 "CPU cores must be greater than 0".to_string(),
847 ));
848 }
849 }
850
851 if let Some(memory) = self.max_memory {
852 if memory == 0 {
853 return Err(SklearsError::InvalidInput(
854 "Memory must be greater than 0".to_string(),
855 ));
856 }
857 }
858
859 if let Some(tasks) = self.max_concurrent_tasks {
860 if tasks == 0 {
861 return Err(SklearsError::InvalidInput(
862 "Concurrent tasks must be greater than 0".to_string(),
863 ));
864 }
865 }
866
867 Ok(())
868 }
869}
870
871impl PerformanceGoals {
872 pub fn validate(&self) -> SklResult<()> {
873 if let Some(throughput) = self.target_throughput {
874 if throughput <= 0.0 {
875 return Err(SklearsError::InvalidInput(
876 "Throughput must be positive".to_string(),
877 ));
878 }
879 }
880
881 if let Some(latency) = self.target_latency {
882 if latency <= 0.0 {
883 return Err(SklearsError::InvalidInput(
884 "Latency must be positive".to_string(),
885 ));
886 }
887 }
888
889 if let Some(utilization) = self.target_utilization {
890 if !(0.0..=100.0).contains(&utilization) {
891 return Err(SklearsError::InvalidInput(
892 "Utilization must be between 0 and 100".to_string(),
893 ));
894 }
895 }
896
897 Ok(())
898 }
899}
900
901impl FaultToleranceConfig {
902 pub fn validate(&self) -> SklResult<()> {
903 if self.enable_retry && self.max_retries == 0 {
904 return Err(SklearsError::InvalidInput(
905 "Max retries must be greater than 0 when retry is enabled".to_string(),
906 ));
907 }
908
909 if self.enable_circuit_breaker && self.circuit_breaker_threshold == 0 {
910 return Err(SklearsError::InvalidInput(
911 "Circuit breaker threshold must be greater than 0".to_string(),
912 ));
913 }
914
915 Ok(())
916 }
917}
918
919impl MonitoringConfig {
920 pub fn validate(&self) -> SklResult<()> {
921 if self.collection_interval.as_millis() == 0 {
922 return Err(SklearsError::InvalidInput(
923 "Collection interval must be greater than 0".to_string(),
924 ));
925 }
926
927 Ok(())
928 }
929}
930
931impl IoLimits {
932 pub fn validate(&self) -> SklResult<()> {
933 if let Some(concurrent) = self.max_concurrent_io {
934 if concurrent == 0 {
935 return Err(SklearsError::InvalidInput(
936 "Concurrent I/O must be greater than 0".to_string(),
937 ));
938 }
939 }
940
941 if let Some(buffer_size) = self.buffer_size {
942 if buffer_size == 0 {
943 return Err(SklearsError::InvalidInput(
944 "Buffer size must be greater than 0".to_string(),
945 ));
946 }
947 }
948
949 Ok(())
950 }
951}
952
953#[allow(non_snake_case)]
954#[cfg(test)]
955mod tests {
956 use super::*;
957
958 #[test]
959 fn test_default_config() {
960 let config = ExecutionEngineConfig::default();
961 assert_eq!(config.name, "default_engine");
962 assert_eq!(config.default_strategy, "sequential");
963 assert!(config.validate().is_ok());
964 }
965
966 #[test]
967 fn test_resource_constraints_validation() {
968 let mut constraints = ResourceConstraints::default();
969 assert!(constraints.validate().is_ok());
970
971 constraints.max_cpu_cores = Some(0);
973 assert!(constraints.validate().is_err());
974
975 constraints.max_cpu_cores = Some(4);
977 constraints.max_memory = Some(0);
978 assert!(constraints.validate().is_err());
979 }
980
981 #[test]
982 fn test_performance_goals_validation() {
983 let mut goals = PerformanceGoals::default();
984 assert!(goals.validate().is_ok());
985
986 goals.target_throughput = Some(-1.0);
988 assert!(goals.validate().is_err());
989
990 goals.target_throughput = Some(100.0);
992 goals.target_utilization = Some(150.0);
993 assert!(goals.validate().is_err());
994 }
995
996 #[test]
997 fn test_fault_tolerance_validation() {
998 let mut config = FaultToleranceConfig::default();
999 assert!(config.validate().is_ok());
1000
1001 config.enable_retry = true;
1003 config.max_retries = 0;
1004 assert!(config.validate().is_err());
1005 }
1006
1007 #[test]
1008 fn test_backoff_strategy() {
1009 let fixed = BackoffStrategy::Fixed {
1010 delay: Duration::from_millis(100),
1011 };
1012 let linear = BackoffStrategy::Linear {
1013 delay: Duration::from_millis(100),
1014 };
1015 let exponential = BackoffStrategy::Exponential {
1016 base_delay: Duration::from_millis(100),
1017 max_delay: Duration::from_secs(30),
1018 };
1019
1020 assert!(matches!(fixed, BackoffStrategy::Fixed { .. }));
1022 assert!(matches!(linear, BackoffStrategy::Linear { .. }));
1023 assert!(matches!(exponential, BackoffStrategy::Exponential { .. }));
1024 }
1025
1026 #[test]
1027 fn test_energy_efficiency_config() {
1028 let mut config = EnergyEfficiencyGoal::default();
1029 assert!(!config.enable_power_capping);
1030 assert!(config.dynamic_frequency_scaling);
1031
1032 config.enable_power_capping = true;
1033 config.target_power_consumption = Some(100.0);
1034 assert_eq!(config.target_power_consumption, Some(100.0));
1035 }
1036
1037 #[test]
1038 fn test_monitoring_config() {
1039 let config = MonitoringConfig::default();
1040 assert!(!config.enable_detailed_metrics);
1041 assert!(!config.enable_distributed_tracing);
1042 assert_eq!(config.collection_interval, Duration::from_secs(10));
1043 }
1044
1045 #[test]
1046 fn test_io_limits() {
1047 let limits = IoLimits::default();
1048 assert_eq!(limits.io_priority, IoPriority::Normal);
1049 assert_eq!(limits.io_scheduler, IoScheduler::CFQ);
1050 assert_eq!(limits.buffer_size, Some(64 * 1024));
1051 }
1052}