1use sklears_core::error::Result as SklResult;
8use std::any::Any;
9use std::collections::HashMap;
10use std::fmt;
11use std::time::{Duration, SystemTime};
12
13pub struct ExecutionTask {
18 pub id: String,
20
21 pub task_type: TaskType,
23
24 pub task_fn: Box<dyn Fn() -> SklResult<()> + Send + Sync>,
26
27 pub metadata: TaskMetadata,
29
30 pub requirements: TaskRequirements,
32
33 pub constraints: TaskConstraints,
35}
36
37impl fmt::Debug for ExecutionTask {
38 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
39 f.debug_struct("ExecutionTask")
40 .field("id", &self.id)
41 .field("task_type", &self.task_type)
42 .field("task_fn", &"<function>")
43 .field("metadata", &self.metadata)
44 .field("requirements", &self.requirements)
45 .field("constraints", &self.constraints)
46 .finish()
47 }
48}
49
50impl Clone for ExecutionTask {
51 fn clone(&self) -> Self {
52 Self {
54 id: self.id.clone(),
55 task_type: self.task_type.clone(),
56 task_fn: Box::new(|| Ok(())), metadata: self.metadata.clone(),
58 requirements: self.requirements.clone(),
59 constraints: self.constraints.clone(),
60 }
61 }
62}
63
64#[derive(Debug, Clone, PartialEq, Eq, Hash)]
69pub enum TaskType {
70 Transform,
72
73 Fit,
75
76 Predict,
78
79 Preprocess,
81
82 Postprocess,
84
85 Validate,
87
88 FeatureEngineering,
90
91 Evaluate,
93
94 HyperparameterOptimization,
96
97 CrossValidation,
99
100 Ensemble,
102
103 DataIO,
105
106 Visualization,
108
109 Custom(String),
111}
112
113#[derive(Debug, Clone, PartialEq, Eq)]
117pub enum TaskStatus {
118 Pending,
120
121 Running,
123
124 Completed,
126
127 Failed,
129
130 Cancelled,
132
133 Timeout,
135
136 Retrying,
138
139 Paused,
141
142 RollingBack,
144}
145
146#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
151pub enum TaskPriority {
152 Low,
154
155 Normal,
157
158 High,
160
161 Critical,
163
164 System,
166}
167
168#[derive(Debug, Clone)]
173pub struct TaskMetadata {
174 pub name: String,
176
177 pub description: Option<String>,
179
180 pub tags: Vec<String>,
182
183 pub created_at: SystemTime,
185
186 pub estimated_duration: Option<Duration>,
188
189 pub priority: TaskPriority,
191
192 pub dependencies: Vec<String>,
194
195 pub group_id: Option<String>,
197
198 pub submitted_by: Option<String>,
200
201 pub custom_metadata: HashMap<String, MetadataValue>,
203
204 pub retry_config: Option<TaskRetryConfig>,
206
207 pub timeout_config: Option<TaskTimeoutConfig>,
209}
210
211#[derive(Debug, Clone)]
213pub enum MetadataValue {
214 String(String),
216 Integer(i64),
218 Float(f64),
220 Boolean(bool),
222 Timestamp(SystemTime),
224 Duration(Duration),
226 Array(Vec<MetadataValue>),
228 Object(HashMap<String, MetadataValue>),
230}
231
232#[derive(Debug, Clone)]
234pub struct TaskRetryConfig {
235 pub max_retries: usize,
237
238 pub retry_delay: Duration,
240
241 pub backoff_strategy: RetryBackoffStrategy,
243
244 pub retry_conditions: Vec<RetryCondition>,
246
247 pub max_retry_time: Option<Duration>,
249}
250
251#[derive(Debug, Clone)]
253pub enum RetryBackoffStrategy {
254 Fixed,
256
257 Linear { increment: Duration },
259
260 Exponential { multiplier: f64 },
262
263 JitteredExponential { multiplier: f64, jitter: f64 },
265
266 Custom { strategy_name: String },
268}
269
270#[derive(Debug, Clone)]
272pub enum RetryCondition {
273 AnyFailure,
275
276 ErrorType(String),
278
279 ResourceUnavailable,
281
282 Timeout,
284
285 TransientFailure,
287
288 Custom(String),
290}
291
292#[derive(Debug, Clone)]
294pub struct TaskTimeoutConfig {
295 pub total_timeout: Duration,
297
298 pub allocation_timeout: Option<Duration>,
300
301 pub initialization_timeout: Option<Duration>,
303
304 pub execution_timeout: Option<Duration>,
306
307 pub cleanup_timeout: Option<Duration>,
309
310 pub timeout_action: TimeoutAction,
312}
313
314#[derive(Debug, Clone)]
316pub enum TimeoutAction {
317 Cancel,
319
320 GracefulShutdown { grace_period: Duration },
322
323 ForceKill,
325
326 Migrate { target_strategy: String },
328
329 Custom { handler_name: String },
331}
332
333#[derive(Debug, Clone, Default)]
338pub struct TaskRequirements {
339 pub cpu_cores: Option<usize>,
341
342 pub memory_bytes: Option<u64>,
344
345 pub io_bandwidth: Option<u64>,
347
348 pub gpu_memory: Option<u64>,
350
351 pub network_bandwidth: Option<u64>,
353
354 pub storage_space: Option<u64>,
356
357 pub gpu_requirements: Option<GpuRequirements>,
359
360 pub cpu_requirements: Option<CpuRequirements>,
362
363 pub memory_requirements: Option<MemoryRequirements>,
365
366 pub io_requirements: Option<IoRequirements>,
368
369 pub network_requirements: Option<NetworkRequirements>,
371
372 pub custom_requirements: HashMap<String, ResourceRequirement>,
374}
375
376#[derive(Debug, Clone)]
378pub struct GpuRequirements {
379 pub min_compute_capability: Option<(u32, u32)>,
381
382 pub required_architecture: Option<String>,
384
385 pub min_memory_bandwidth: Option<u64>,
387
388 pub required_features: Vec<String>,
390
391 pub affinity_preferences: Vec<usize>,
393}
394
395#[derive(Debug, Clone)]
397pub struct CpuRequirements {
398 pub min_frequency: Option<f64>,
400
401 pub required_instruction_sets: Vec<String>,
403
404 pub required_features: Vec<String>,
406
407 pub numa_preferences: Option<NumaPreferences>,
409
410 pub cache_requirements: Option<CacheRequirements>,
412}
413
414#[derive(Debug, Clone)]
416pub struct NumaPreferences {
417 pub preferred_nodes: Vec<usize>,
419
420 pub local_memory_preference: f64,
422
423 pub max_numa_distance: Option<usize>,
425}
426
427#[derive(Debug, Clone)]
429pub struct CacheRequirements {
430 pub min_l1_cache: Option<u64>,
432
433 pub min_l2_cache: Option<u64>,
435
436 pub min_l3_cache: Option<u64>,
438
439 pub cache_line_size: Option<usize>,
441}
442
443#[derive(Debug, Clone)]
445pub struct MemoryRequirements {
446 pub memory_type: Option<String>,
448
449 pub min_bandwidth: Option<u64>,
451
452 pub max_latency: Option<Duration>,
454
455 pub huge_pages: Option<HugePageRequirements>,
457
458 pub protection: Option<MemoryProtection>,
460}
461
462#[derive(Debug, Clone)]
464pub struct HugePageRequirements {
465 pub page_size: HugePageSize,
467
468 pub page_count: usize,
470
471 pub pool_preference: Option<String>,
473}
474
475#[derive(Debug, Clone)]
477pub enum HugePageSize {
478 Size2MB,
480
481 Size1GB,
483
484 Custom(u64),
486}
487
488#[derive(Debug, Clone)]
490pub struct MemoryProtection {
491 pub encryption: bool,
493
494 pub isolation: bool,
496
497 pub permissions: MemoryPermissions,
499}
500
501#[derive(Debug, Clone)]
503pub struct MemoryPermissions {
504 pub read: bool,
506
507 pub write: bool,
509
510 pub execute: bool,
512}
513
514#[derive(Debug, Clone)]
516pub struct IoRequirements {
517 pub storage_type: Option<StorageType>,
519
520 pub min_iops: Option<u64>,
522
523 pub max_latency: Option<Duration>,
525
526 pub access_patterns: Vec<IoAccessPattern>,
528
529 pub durability: Option<DurabilityLevel>,
531}
532
533#[derive(Debug, Clone)]
535pub enum StorageType {
536 HDD,
538 SSD,
540 NVMe,
542 Memory,
544 Network,
546 Custom(String),
548}
549
550#[derive(Debug, Clone)]
552pub enum IoAccessPattern {
553 Sequential,
555 Random,
557 Mixed,
559 WriteHeavy,
561 ReadHeavy,
563 StreamingRead,
565 StreamingWrite,
567}
568
569#[derive(Debug, Clone)]
571pub enum DurabilityLevel {
572 None,
574
575 BufferWrite,
577
578 SyncWrite,
580
581 Replicated { replica_count: usize },
583
584 Custom(String),
586}
587
588#[derive(Debug, Clone)]
590pub struct NetworkRequirements {
591 pub max_latency: Option<Duration>,
593
594 pub min_bandwidth: Option<u64>,
596
597 pub max_packet_loss: Option<f64>,
599
600 pub required_protocols: Vec<String>,
602
603 pub qos_requirements: Option<QosRequirements>,
605}
606
607#[derive(Debug, Clone)]
609pub struct QosRequirements {
610 pub traffic_class: TrafficClass,
612
613 pub bandwidth_guarantee: Option<u64>,
615
616 pub latency_guarantee: Option<Duration>,
618
619 pub jitter_tolerance: Option<Duration>,
621}
622
623#[derive(Debug, Clone)]
625pub enum TrafficClass {
626 BestEffort,
628 Bronze,
630 Silver,
632 Gold,
634 Platinum,
636 RealTime,
638 Custom(String),
640}
641
642#[derive(Debug, Clone)]
644pub struct ResourceRequirement {
645 pub resource_type: String,
647
648 pub required_amount: f64,
650
651 pub min_amount: Option<f64>,
653
654 pub max_amount: Option<f64>,
656
657 pub unit: String,
659
660 pub properties: HashMap<String, String>,
662}
663
664#[derive(Debug, Clone, Default)]
669pub struct TaskConstraints {
670 pub max_execution_time: Option<Duration>,
672
673 pub deadline: Option<SystemTime>,
675
676 pub location: Option<ExecutionLocation>,
678
679 pub affinity: Option<TaskAffinity>,
681
682 pub isolation: Option<IsolationRequirements>,
684
685 pub security: Option<SecurityConstraints>,
687
688 pub compliance: Option<ComplianceRequirements>,
690
691 pub custom_constraints: HashMap<String, ConstraintValue>,
693}
694
695#[derive(Debug, Clone)]
700pub enum ExecutionLocation {
701 Local,
703
704 Remote { node_id: String },
706
707 Cloud {
709 provider: String,
710 region: String,
711 availability_zone: Option<String>,
712 },
713
714 Edge {
716 device_id: String,
717 device_type: String,
718 },
719
720 Container {
722 container_id: String,
723 orchestrator: String,
724 },
725
726 VirtualMachine { vm_id: String, hypervisor: String },
728
729 Custom {
731 location_type: String,
732 parameters: HashMap<String, String>,
733 },
734}
735
736#[derive(Debug, Clone)]
738pub struct TaskAffinity {
739 pub cpu_affinity: Option<Vec<usize>>,
741
742 pub memory_affinity: Option<Vec<usize>>,
744
745 pub node_affinity: Option<Vec<String>>,
747
748 pub gpu_affinity: Option<Vec<usize>>,
750
751 pub storage_affinity: Option<Vec<String>>,
753
754 pub network_affinity: Option<Vec<String>>,
756
757 pub affinity_strength: AffinityStrength,
759}
760
761#[derive(Debug, Clone)]
763pub enum AffinityStrength {
764 Preferred,
766
767 Required,
769
770 AntiAffinity,
772
773 Custom(String),
775}
776
777#[derive(Debug, Clone)]
779pub struct IsolationRequirements {
780 pub process_isolation: IsolationLevel,
782
783 pub memory_isolation: IsolationLevel,
785
786 pub network_isolation: IsolationLevel,
788
789 pub filesystem_isolation: IsolationLevel,
791
792 pub custom_isolation: HashMap<String, IsolationLevel>,
794}
795
796#[derive(Debug, Clone)]
798pub enum IsolationLevel {
799 None,
801
802 Basic,
804
805 Strong,
807
808 Complete,
810
811 Custom(String),
813}
814
815#[derive(Debug, Clone)]
817pub struct SecurityConstraints {
818 pub clearance_level: Option<String>,
820
821 pub encryption_requirements: EncryptionRequirements,
823
824 pub access_control: AccessControlRequirements,
826
827 pub audit_requirements: AuditRequirements,
829
830 pub data_classification: Option<DataClassification>,
832}
833
834#[derive(Debug, Clone)]
836pub struct EncryptionRequirements {
837 pub at_rest: bool,
839
840 pub in_transit: bool,
842
843 pub in_memory: bool,
845
846 pub algorithms: Vec<String>,
848
849 pub min_key_length: Option<usize>,
851}
852
853#[derive(Debug, Clone)]
855pub struct AccessControlRequirements {
856 pub authentication_methods: Vec<String>,
858
859 pub authorization_levels: Vec<String>,
861
862 pub rbac_requirements: Option<RbacRequirements>,
864
865 pub abac_requirements: Option<AbacRequirements>,
867}
868
869#[derive(Debug, Clone)]
871pub struct RbacRequirements {
872 pub required_roles: Vec<String>,
874
875 pub prohibited_roles: Vec<String>,
877
878 pub hierarchy_requirements: Option<String>,
880}
881
882#[derive(Debug, Clone)]
884pub struct AbacRequirements {
885 pub required_attributes: HashMap<String, String>,
887
888 pub policies: Vec<String>,
890
891 pub context_requirements: HashMap<String, String>,
893}
894
895#[derive(Debug, Clone)]
897pub struct AuditRequirements {
898 pub enable_logging: bool,
900
901 pub detail_level: AuditDetailLevel,
903
904 pub required_events: Vec<String>,
906
907 pub retention_period: Duration,
909
910 pub integrity_requirements: AuditIntegrityRequirements,
912}
913
914#[derive(Debug, Clone)]
916pub enum AuditDetailLevel {
917 Basic,
919 Detailed,
921 Comprehensive,
923 Custom(String),
925}
926
927#[derive(Debug, Clone)]
929pub struct AuditIntegrityRequirements {
930 pub digital_signatures: bool,
932
933 pub tamper_detection: bool,
935
936 pub log_encryption: bool,
938
939 pub immutable_logs: bool,
941}
942
943#[derive(Debug, Clone)]
945pub enum DataClassification {
946 Public,
948 Internal,
950 Confidential,
952 Restricted,
954 TopSecret,
956 Custom(String),
958}
959
960#[derive(Debug, Clone)]
962pub struct ComplianceRequirements {
963 pub frameworks: Vec<ComplianceFramework>,
965
966 pub data_residency: Option<DataResidencyRequirements>,
968
969 pub privacy_requirements: Option<PrivacyRequirements>,
971
972 pub custom_requirements: HashMap<String, String>,
974}
975
976#[derive(Debug, Clone)]
978pub enum ComplianceFramework {
979 GDPR,
981 HIPAA,
983 SOX,
985 PciDss,
987 ISO27001,
989 FedRAMP,
991 SOC2,
993 Custom(String),
995}
996
997#[derive(Debug, Clone)]
999pub struct DataResidencyRequirements {
1000 pub allowed_countries: Vec<String>,
1002
1003 pub prohibited_countries: Vec<String>,
1005
1006 pub allowed_regions: Vec<String>,
1008
1009 pub sovereignty_requirements: bool,
1011}
1012
1013#[derive(Debug, Clone)]
1015pub struct PrivacyRequirements {
1016 pub pii_handling: PiiHandlingRequirements,
1018
1019 pub anonymization: bool,
1021
1022 pub consent_requirements: ConsentRequirements,
1024
1025 pub right_to_be_forgotten: bool,
1027}
1028
1029#[derive(Debug, Clone)]
1031pub struct PiiHandlingRequirements {
1032 pub encryption_required: bool,
1034
1035 pub access_logging: bool,
1037
1038 pub retention_limits: Option<Duration>,
1040
1041 pub processing_purposes: Vec<String>,
1043}
1044
1045#[derive(Debug, Clone)]
1047pub struct ConsentRequirements {
1048 pub explicit_consent: bool,
1050
1051 pub consent_verification: bool,
1053
1054 pub withdrawal_support: bool,
1056
1057 pub granularity_level: ConsentGranularity,
1059}
1060
1061#[derive(Debug, Clone)]
1063pub enum ConsentGranularity {
1064 Global,
1066 PerPurpose,
1068 PerDataType,
1070 PerOperation,
1072 Custom(String),
1074}
1075
1076#[derive(Debug, Clone)]
1078pub enum ConstraintValue {
1079 String(String),
1081 Integer(i64),
1083 Float(f64),
1085 Boolean(bool),
1087 Duration(Duration),
1089 Timestamp(SystemTime),
1091 Array(Vec<ConstraintValue>),
1093 Object(HashMap<String, ConstraintValue>),
1095}
1096
1097#[derive(Debug)]
1102pub struct TaskResult {
1103 pub task_id: String,
1105
1106 pub status: TaskStatus,
1108
1109 pub data: Option<Box<dyn Any + Send>>,
1111
1112 pub metrics: TaskExecutionMetrics,
1114
1115 pub error: Option<TaskError>,
1117}
1118
1119#[derive(Debug, Clone)]
1124pub struct TaskExecutionMetrics {
1125 pub start_time: SystemTime,
1127
1128 pub end_time: Option<SystemTime>,
1130
1131 pub duration: Option<Duration>,
1133
1134 pub resource_usage: TaskResourceUsage,
1136
1137 pub performance: TaskPerformanceMetrics,
1139}
1140
1141impl Default for TaskExecutionMetrics {
1142 fn default() -> Self {
1143 Self {
1144 start_time: SystemTime::UNIX_EPOCH,
1145 end_time: None,
1146 duration: None,
1147 resource_usage: TaskResourceUsage::default(),
1148 performance: TaskPerformanceMetrics::default(),
1149 }
1150 }
1151}
1152
1153#[derive(Debug, Clone, Default)]
1155pub struct TaskResourceUsage {
1156 pub cpu_percent: f64,
1158
1159 pub memory_bytes: u64,
1161
1162 pub io_operations: u64,
1164
1165 pub network_bytes: u64,
1167
1168 pub gpu_memory_bytes: Option<u64>,
1170
1171 pub gpu_utilization_percent: Option<f64>,
1173
1174 pub storage_bytes: Option<u64>,
1176
1177 pub energy_consumption: Option<f64>,
1179}
1180
1181#[derive(Debug, Clone, Default)]
1183pub struct TaskPerformanceMetrics {
1184 pub throughput: f64,
1186
1187 pub latency: f64,
1189
1190 pub cache_hit_rate: f64,
1192
1193 pub error_rate: f64,
1195
1196 pub quality_metrics: HashMap<String, f64>,
1198
1199 pub efficiency_metrics: EfficiencyMetrics,
1201}
1202
1203#[derive(Debug, Clone, Default)]
1205pub struct EfficiencyMetrics {
1206 pub cpu_efficiency: f64,
1208
1209 pub memory_efficiency: f64,
1211
1212 pub io_efficiency: f64,
1214
1215 pub energy_efficiency: Option<f64>,
1217
1218 pub overall_efficiency: f64,
1220}
1221
1222#[derive(Debug, Clone)]
1227pub struct TaskError {
1228 pub error_type: String,
1230
1231 pub message: String,
1233
1234 pub code: Option<i32>,
1236
1237 pub stack_trace: Option<String>,
1239
1240 pub context: HashMap<String, String>,
1242
1243 pub recovery_suggestions: Vec<String>,
1245
1246 pub related_errors: Vec<RelatedError>,
1248
1249 pub severity: ErrorSeverity,
1251
1252 pub category: ErrorCategory,
1254}
1255
1256#[derive(Debug, Clone)]
1258pub struct RelatedError {
1259 pub error_type: String,
1261
1262 pub message: String,
1264
1265 pub relationship: ErrorRelationship,
1267}
1268
1269#[derive(Debug, Clone)]
1271pub enum ErrorRelationship {
1272 Cause,
1274
1275 Effect,
1277
1278 Related,
1280
1281 Concurrent,
1283}
1284
1285#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
1287pub enum ErrorSeverity {
1288 Info,
1290
1291 Warning,
1293
1294 Minor,
1296
1297 Major,
1299
1300 Critical,
1302
1303 Fatal,
1305}
1306
1307#[derive(Debug, Clone)]
1309pub enum ErrorCategory {
1310 Resource,
1312
1313 Configuration,
1315
1316 Validation,
1318
1319 Network,
1321
1322 IO,
1324
1325 Security,
1327
1328 Timeout,
1330
1331 Dependency,
1333
1334 System,
1336
1337 User,
1339
1340 External,
1342
1343 Custom(String),
1345}
1346
1347impl Default for TaskMetadata {
1350 fn default() -> Self {
1351 Self {
1352 name: "unnamed_task".to_string(),
1353 description: None,
1354 tags: Vec::new(),
1355 created_at: SystemTime::now(),
1356 estimated_duration: None,
1357 priority: TaskPriority::Normal,
1358 dependencies: Vec::new(),
1359 group_id: None,
1360 submitted_by: None,
1361 custom_metadata: HashMap::new(),
1362 retry_config: None,
1363 timeout_config: None,
1364 }
1365 }
1366}
1367
1368impl ExecutionTask {
1369 pub fn new<F>(id: String, name: String, task_fn: F) -> Self
1371 where
1372 F: Fn() -> SklResult<()> + Send + Sync + 'static,
1373 {
1374 Self {
1375 id,
1376 task_type: TaskType::Custom("generic".to_string()),
1377 task_fn: Box::new(task_fn),
1378 metadata: TaskMetadata {
1379 name,
1380 ..Default::default()
1381 },
1382 requirements: TaskRequirements::default(),
1383 constraints: TaskConstraints::default(),
1384 }
1385 }
1386
1387 pub fn with_config<F>(
1389 id: String,
1390 task_type: TaskType,
1391 task_fn: F,
1392 metadata: TaskMetadata,
1393 requirements: TaskRequirements,
1394 constraints: TaskConstraints,
1395 ) -> Self
1396 where
1397 F: Fn() -> SklResult<()> + Send + Sync + 'static,
1398 {
1399 Self {
1400 id,
1401 task_type,
1402 task_fn: Box::new(task_fn),
1403 metadata,
1404 requirements,
1405 constraints,
1406 }
1407 }
1408
1409 #[must_use]
1411 pub fn estimated_duration(&self) -> Duration {
1412 self.metadata
1413 .estimated_duration
1414 .unwrap_or(Duration::from_secs(60))
1415 }
1416
1417 #[must_use]
1419 pub fn has_dependencies(&self) -> bool {
1420 !self.metadata.dependencies.is_empty()
1421 }
1422
1423 #[must_use]
1425 pub fn priority(&self) -> TaskPriority {
1426 self.metadata.priority.clone()
1427 }
1428
1429 #[must_use]
1431 pub fn requires_gpu(&self) -> bool {
1432 self.requirements.gpu_memory.is_some() || self.requirements.gpu_requirements.is_some()
1433 }
1434
1435 #[must_use]
1437 pub fn is_cpu_intensive(&self) -> bool {
1438 self.requirements.cpu_cores.unwrap_or(1) > 1
1439 }
1440
1441 #[must_use]
1443 pub fn is_memory_intensive(&self) -> bool {
1444 self.requirements.memory_bytes.unwrap_or(0) > 1024 * 1024 * 1024 }
1446
1447 #[must_use]
1449 pub fn is_io_intensive(&self) -> bool {
1450 self.requirements.io_bandwidth.is_some()
1451 || self.requirements.storage_space.unwrap_or(0) > 100 * 1024 * 1024 }
1453
1454 #[must_use]
1456 pub fn is_network_intensive(&self) -> bool {
1457 self.requirements.network_bandwidth.is_some()
1458 || self.requirements.network_requirements.is_some()
1459 }
1460}
1461
1462impl TaskResult {
1463 #[must_use]
1465 pub fn is_success(&self) -> bool {
1466 matches!(self.status, TaskStatus::Completed)
1467 }
1468
1469 #[must_use]
1471 pub fn is_failure(&self) -> bool {
1472 matches!(self.status, TaskStatus::Failed)
1473 }
1474
1475 #[must_use]
1477 pub fn execution_duration(&self) -> Option<Duration> {
1478 self.metrics.duration
1479 }
1480
1481 #[must_use]
1483 pub fn error_message(&self) -> Option<&str> {
1484 self.error.as_ref().map(|e| e.message.as_str())
1485 }
1486}
1487
1488#[allow(non_snake_case)]
1489#[cfg(test)]
1490mod tests {
1491 use super::*;
1492
1493 #[test]
1494 fn test_task_creation() {
1495 let task = ExecutionTask::new("test_task".to_string(), "Test Task".to_string(), || Ok(()));
1496
1497 assert_eq!(task.id, "test_task");
1498 assert_eq!(task.metadata.name, "Test Task");
1499 assert_eq!(task.metadata.priority, TaskPriority::Normal);
1500 }
1501
1502 #[test]
1503 fn test_task_priority_ordering() {
1504 assert!(TaskPriority::Critical > TaskPriority::High);
1505 assert!(TaskPriority::High > TaskPriority::Normal);
1506 assert!(TaskPriority::Normal > TaskPriority::Low);
1507 assert!(TaskPriority::System > TaskPriority::Critical);
1508 }
1509
1510 #[test]
1511 fn test_task_status_variants() {
1512 let statuses = vec![
1513 TaskStatus::Pending,
1514 TaskStatus::Running,
1515 TaskStatus::Completed,
1516 TaskStatus::Failed,
1517 TaskStatus::Cancelled,
1518 TaskStatus::Timeout,
1519 TaskStatus::Retrying,
1520 TaskStatus::Paused,
1521 TaskStatus::RollingBack,
1522 ];
1523
1524 for status in statuses {
1525 assert!(matches!(status, _)); }
1527 }
1528
1529 #[test]
1530 fn test_task_type_variants() {
1531 let types = vec![
1532 TaskType::Transform,
1533 TaskType::Fit,
1534 TaskType::Predict,
1535 TaskType::Preprocess,
1536 TaskType::Postprocess,
1537 TaskType::Validate,
1538 TaskType::Custom("test".to_string()),
1539 ];
1540
1541 for task_type in types {
1542 assert!(matches!(task_type, _)); }
1544 }
1545
1546 #[test]
1547 fn test_task_resource_checks() {
1548 let mut task =
1549 ExecutionTask::new("test_task".to_string(), "Test Task".to_string(), || Ok(()));
1550
1551 task.requirements.gpu_memory = Some(1024 * 1024 * 1024); assert!(task.requires_gpu());
1554
1555 task.requirements.cpu_cores = Some(8);
1557 assert!(task.is_cpu_intensive());
1558
1559 task.requirements.memory_bytes = Some(2 * 1024 * 1024 * 1024); assert!(task.is_memory_intensive());
1562
1563 task.requirements.storage_space = Some(500 * 1024 * 1024); assert!(task.is_io_intensive());
1566 }
1567
1568 #[test]
1569 fn test_task_result_status_checks() {
1570 let mut result = TaskResult {
1571 task_id: "test".to_string(),
1572 status: TaskStatus::Completed,
1573 data: None,
1574 metrics: TaskExecutionMetrics::default(),
1575 error: None,
1576 };
1577
1578 assert!(result.is_success());
1579 assert!(!result.is_failure());
1580
1581 result.status = TaskStatus::Failed;
1582 assert!(!result.is_success());
1583 assert!(result.is_failure());
1584 }
1585
1586 #[test]
1587 fn test_error_severity_ordering() {
1588 assert!(ErrorSeverity::Fatal > ErrorSeverity::Critical);
1589 assert!(ErrorSeverity::Critical > ErrorSeverity::Major);
1590 assert!(ErrorSeverity::Major > ErrorSeverity::Minor);
1591 assert!(ErrorSeverity::Minor > ErrorSeverity::Warning);
1592 assert!(ErrorSeverity::Warning > ErrorSeverity::Info);
1593 }
1594
1595 #[test]
1596 fn test_metadata_value_variants() {
1597 let values = vec![
1598 MetadataValue::String("test".to_string()),
1599 MetadataValue::Integer(42),
1600 MetadataValue::Float(3.14),
1601 MetadataValue::Boolean(true),
1602 MetadataValue::Timestamp(SystemTime::now()),
1603 MetadataValue::Duration(Duration::from_secs(60)),
1604 ];
1605
1606 for value in values {
1607 assert!(matches!(value, _)); }
1609 }
1610
1611 #[test]
1612 fn test_execution_location_variants() {
1613 let locations = vec![
1614 ExecutionLocation::Local,
1615 ExecutionLocation::Remote {
1616 node_id: "node1".to_string(),
1617 },
1618 ExecutionLocation::Cloud {
1619 provider: "AWS".to_string(),
1620 region: "us-east-1".to_string(),
1621 availability_zone: Some("us-east-1a".to_string()),
1622 },
1623 ExecutionLocation::Edge {
1624 device_id: "edge1".to_string(),
1625 device_type: "raspberry_pi".to_string(),
1626 },
1627 ];
1628
1629 for location in locations {
1630 assert!(matches!(location, _)); }
1632 }
1633}