Skip to main content

trustformers_mobile/lifecycle/
tasks.rs

1//! Background Task Management Types
2//!
3//! This module contains types for managing background tasks, execution context,
4//! and resource requirements.
5
6use crate::lifecycle::config::{SchedulingStrategy, TaskPriority, TaskType};
7use serde::{Deserialize, Serialize};
8use std::collections::HashMap;
9use std::sync::Arc;
10use std::time::{Duration, Instant};
11
12/// Background task definition
13#[derive(Debug, Clone, Serialize, Deserialize)]
14pub struct BackgroundTask {
15    /// Unique task identifier
16    pub task_id: String,
17    /// Task type
18    pub task_type: TaskType,
19    /// Task priority
20    pub priority: TaskPriority,
21    /// Scheduling strategy
22    pub scheduling_strategy: SchedulingStrategy,
23    /// Resource requirements
24    pub resource_requirements: ResourceRequirements,
25    /// Execution constraints
26    pub execution_constraints: ExecutionConstraints,
27    /// Task metadata
28    pub metadata: TaskMetadata,
29}
30
31/// Resource requirements for tasks
32#[derive(Debug, Clone, Serialize, Deserialize)]
33pub struct ResourceRequirements {
34    /// Minimum CPU allocation (%)
35    pub min_cpu_percent: u8,
36    /// Maximum CPU allocation (%)
37    pub max_cpu_percent: u8,
38    /// Minimum memory allocation (MB)
39    pub min_memory_mb: usize,
40    /// Maximum memory allocation (MB)
41    pub max_memory_mb: usize,
42    /// Network bandwidth requirement (Mbps)
43    pub network_bandwidth_mbps: Option<f32>,
44    /// GPU requirement
45    pub requires_gpu: bool,
46    /// Storage I/O requirement (MB/s)
47    pub storage_io_mbps: Option<f32>,
48    /// Execution time estimate (seconds)
49    pub estimated_execution_time_seconds: u64,
50}
51
52/// Task execution constraints
53#[derive(Debug, Clone, Serialize, Deserialize)]
54pub struct ExecutionConstraints {
55    /// Maximum execution time (seconds)
56    pub max_execution_time_seconds: u64,
57    /// Retry attempts on failure
58    pub retry_attempts: u32,
59    /// Retry delay (seconds)
60    pub retry_delay_seconds: u64,
61    /// Requires network connectivity
62    pub requires_network: bool,
63    /// Minimum battery level (%)
64    pub min_battery_percent: u8,
65    /// Maximum thermal level
66    pub max_thermal_level: crate::lifecycle::config::ThermalLevel,
67    /// Can run in background
68    pub background_eligible: bool,
69    /// User presence required
70    pub requires_user_presence: bool,
71}
72
73/// Task metadata
74#[derive(Debug, Clone, Serialize, Deserialize)]
75pub struct TaskMetadata {
76    /// Task name
77    pub name: String,
78    /// Task description
79    pub description: String,
80    /// Creation timestamp
81    pub created_timestamp: u64,
82    /// Scheduled execution timestamp
83    pub scheduled_timestamp: Option<u64>,
84    /// Last execution timestamp
85    pub last_execution_timestamp: Option<u64>,
86    /// Execution count
87    pub execution_count: usize,
88    /// Success count
89    pub success_count: usize,
90    /// Failure count
91    pub failure_count: usize,
92    /// Tags for categorization
93    pub tags: Vec<String>,
94}
95
96/// Task execution status
97#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
98pub enum TaskStatus {
99    /// Task is pending execution
100    Pending,
101    /// Task is scheduled to run
102    Scheduled,
103    /// Task is currently running
104    Running,
105    /// Task is paused
106    Paused,
107    /// Task completed successfully
108    Completed,
109    /// Task failed
110    Failed,
111    /// Task was cancelled
112    Cancelled,
113    /// Task timed out
114    TimedOut,
115    /// Task was deferred
116    Deferred,
117    /// Task is waiting for resources
118    WaitingForResources,
119    /// Task is waiting for conditions
120    WaitingForConditions,
121}
122
123/// Task execution result
124#[derive(Debug, Clone, Serialize, Deserialize)]
125pub struct TaskResult {
126    /// Task identifier
127    pub task_id: String,
128    /// Execution status
129    pub status: TaskStatus,
130    /// Start timestamp
131    pub start_timestamp: u64,
132    /// End timestamp
133    pub end_timestamp: Option<u64>,
134    /// Actual execution time (seconds)
135    pub execution_time_seconds: f64,
136    /// Resource usage during execution
137    pub resource_usage: TaskResourceUsage,
138    /// Output data (if any)
139    pub output_data: Option<Vec<u8>>,
140    /// Error information (if failed)
141    pub error_info: Option<TaskError>,
142    /// Performance metrics
143    pub performance_metrics: TaskPerformanceMetrics,
144    /// Quality metrics
145    pub quality_metrics: Option<TaskQualityMetrics>,
146}
147
148/// Task resource usage during execution
149#[derive(Debug, Clone, Serialize, Deserialize)]
150pub struct TaskResourceUsage {
151    /// Peak CPU usage (%)
152    pub peak_cpu_percent: f32,
153    /// Average CPU usage (%)
154    pub avg_cpu_percent: f32,
155    /// Peak memory usage (MB)
156    pub peak_memory_mb: usize,
157    /// Average memory usage (MB)
158    pub avg_memory_mb: usize,
159    /// Network data transferred (MB)
160    pub network_data_mb: f32,
161    /// Storage I/O performed (MB)
162    pub storage_io_mb: f32,
163    /// GPU usage (%)
164    pub gpu_usage_percent: Option<f32>,
165    /// Battery consumption (mAh)
166    pub battery_consumption_mah: f32,
167}
168
169/// Task error information
170#[derive(Debug, Clone, Serialize, Deserialize)]
171pub struct TaskError {
172    /// Error code
173    pub error_code: u32,
174    /// Error message
175    pub error_message: String,
176    /// Error category
177    pub error_category: TaskErrorCategory,
178    /// Recoverable error flag
179    pub recoverable: bool,
180    /// Retry recommended flag
181    pub retry_recommended: bool,
182    /// Additional error details
183    pub details: HashMap<String, String>,
184}
185
186/// Task error categories
187#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
188pub enum TaskErrorCategory {
189    ResourceUnavailable,
190    NetworkError,
191    AuthenticationError,
192    PermissionError,
193    DataError,
194    SystemError,
195    TimeoutError,
196    UserCancellation,
197    InternalError,
198    ConfigurationError,
199}
200
201/// Task performance metrics
202#[derive(Debug, Clone, Serialize, Deserialize)]
203pub struct TaskPerformanceMetrics {
204    /// Throughput (operations/second)
205    pub throughput_ops_per_second: f32,
206    /// Latency percentiles (ms)
207    pub latency_percentiles: LatencyPercentiles,
208    /// Error rate (%)
209    pub error_rate_percent: f32,
210    /// Resource efficiency score (0-100)
211    pub resource_efficiency_score: f32,
212    /// Completion rate (%)
213    pub completion_rate_percent: f32,
214}
215
216/// Latency percentile measurements
217#[derive(Debug, Clone, Serialize, Deserialize)]
218pub struct LatencyPercentiles {
219    /// 50th percentile (median) in ms
220    pub p50_ms: f32,
221    /// 90th percentile in ms
222    pub p90_ms: f32,
223    /// 95th percentile in ms
224    pub p95_ms: f32,
225    /// 99th percentile in ms
226    pub p99_ms: f32,
227    /// Maximum latency in ms
228    pub max_ms: f32,
229}
230
231/// Task quality metrics (for ML tasks)
232#[derive(Debug, Clone, Serialize, Deserialize)]
233pub struct TaskQualityMetrics {
234    /// Accuracy score (0-100)
235    pub accuracy_score: f32,
236    /// Precision score (0-100)
237    pub precision_score: f32,
238    /// Recall score (0-100)
239    pub recall_score: f32,
240    /// F1 score (0-100)
241    pub f1_score: f32,
242    /// Model drift score (0-100)
243    pub model_drift_score: Option<f32>,
244    /// Data quality score (0-100)
245    pub data_quality_score: Option<f32>,
246}
247
248/// Background task coordinator
249pub struct BackgroundCoordinator {
250    task_queue: Arc<std::sync::Mutex<Vec<BackgroundTask>>>,
251    running_tasks: Arc<std::sync::Mutex<HashMap<String, TaskExecutionContext>>>,
252    completed_tasks: Arc<std::sync::Mutex<Vec<TaskResult>>>,
253    execution_context: BackgroundExecutionContext,
254    task_registry: TaskRegistry,
255    max_concurrent_tasks: usize,
256}
257
258/// Task execution context
259pub struct TaskExecutionContext {
260    pub task: BackgroundTask,
261    pub start_time: Instant,
262    pub allocated_resources: AllocatedResources,
263    pub status: TaskStatus,
264    pub progress: f32, // 0.0 to 1.0
265}
266
267/// Allocated resources for task execution
268#[derive(Debug, Clone)]
269pub struct AllocatedResources {
270    pub cpu_percent: u8,
271    pub memory_mb: usize,
272    pub network_mbps: Option<f32>,
273    pub gpu_allocation: Option<f32>,
274    pub storage_io_mbps: Option<f32>,
275}
276
277/// Background execution context
278pub struct BackgroundExecutionContext {
279    pub available_cpu_percent: u8,
280    pub available_memory_mb: usize,
281    pub available_network_mbps: f32,
282    pub battery_level_percent: u8,
283    pub thermal_level: crate::lifecycle::config::ThermalLevel,
284    pub network_connected: bool,
285    pub user_present: bool,
286    pub system_load: f32,
287}
288
289/// Task registry for managing task definitions
290pub struct TaskRegistry {
291    registered_tasks: HashMap<TaskType, Vec<BackgroundTask>>,
292    task_templates: HashMap<TaskType, BackgroundTask>,
293}
294
295impl BackgroundCoordinator {
296    /// Create new background coordinator
297    pub fn new(max_concurrent_tasks: usize) -> Self {
298        Self {
299            task_queue: Arc::new(std::sync::Mutex::new(Vec::new())),
300            running_tasks: Arc::new(std::sync::Mutex::new(HashMap::new())),
301            completed_tasks: Arc::new(std::sync::Mutex::new(Vec::new())),
302            execution_context: BackgroundExecutionContext::default(),
303            task_registry: TaskRegistry::new(),
304            max_concurrent_tasks,
305        }
306    }
307
308    /// Schedule a background task
309    pub fn schedule_task(&self, task: BackgroundTask) -> Result<(), Box<dyn std::error::Error>> {
310        let mut queue = self.task_queue.lock().expect("Operation failed");
311        queue.push(task);
312
313        // Sort by priority and scheduling strategy
314        queue.sort_by(|a, b| {
315            b.priority.cmp(&a.priority).then_with(|| {
316                a.scheduling_strategy
317                    .priority_order()
318                    .cmp(&b.scheduling_strategy.priority_order())
319            })
320        });
321
322        Ok(())
323    }
324
325    /// Execute next available task
326    pub fn execute_next_task(&mut self) -> Result<Option<TaskResult>, Box<dyn std::error::Error>> {
327        let running_count = self.running_tasks.lock().expect("Operation failed").len();
328        if running_count >= self.max_concurrent_tasks {
329            return Ok(None);
330        }
331
332        let task = {
333            let mut queue = self.task_queue.lock().expect("Operation failed");
334            if queue.is_empty() {
335                return Ok(None);
336            }
337
338            // Find first executable task based on constraints
339            let mut task_index = None;
340            for (index, task) in queue.iter().enumerate() {
341                if self.can_execute_task(task) {
342                    task_index = Some(index);
343                    break;
344                }
345            }
346
347            match task_index {
348                Some(index) => queue.remove(index),
349                None => return Ok(None),
350            }
351        };
352
353        // Allocate resources and start execution
354        let allocated_resources = self.allocate_resources(&task)?;
355        let execution_context = TaskExecutionContext {
356            task: task.clone(),
357            start_time: Instant::now(),
358            allocated_resources,
359            status: TaskStatus::Running,
360            progress: 0.0,
361        };
362
363        self.running_tasks
364            .lock()
365            .expect("Operation failed")
366            .insert(task.task_id.clone(), execution_context);
367
368        // Execute task (simplified - in real implementation this would be async)
369        let result = self.execute_task_impl(&task)?;
370
371        // Remove from running tasks and add to completed
372        self.running_tasks.lock().expect("Operation failed").remove(&task.task_id);
373        self.completed_tasks.lock().expect("Operation failed").push(result.clone());
374
375        Ok(Some(result))
376    }
377
378    /// Check if task can be executed given current constraints
379    fn can_execute_task(&self, task: &BackgroundTask) -> bool {
380        // Check battery constraints
381        if self.execution_context.battery_level_percent
382            < task.execution_constraints.min_battery_percent
383        {
384            return false;
385        }
386
387        // Check thermal constraints
388        if self.execution_context.thermal_level > task.execution_constraints.max_thermal_level {
389            return false;
390        }
391
392        // Check network constraints
393        if task.execution_constraints.requires_network && !self.execution_context.network_connected
394        {
395            return false;
396        }
397
398        // Check user presence constraints
399        if task.execution_constraints.requires_user_presence && !self.execution_context.user_present
400        {
401            return false;
402        }
403
404        // Check resource availability
405        if task.resource_requirements.min_cpu_percent > self.execution_context.available_cpu_percent
406        {
407            return false;
408        }
409
410        if task.resource_requirements.min_memory_mb > self.execution_context.available_memory_mb {
411            return false;
412        }
413
414        true
415    }
416
417    /// Allocate resources for task execution
418    fn allocate_resources(
419        &self,
420        task: &BackgroundTask,
421    ) -> Result<AllocatedResources, Box<dyn std::error::Error>> {
422        let cpu_percent = task
423            .resource_requirements
424            .min_cpu_percent
425            .min(self.execution_context.available_cpu_percent);
426        let memory_mb = task
427            .resource_requirements
428            .min_memory_mb
429            .min(self.execution_context.available_memory_mb);
430
431        Ok(AllocatedResources {
432            cpu_percent,
433            memory_mb,
434            network_mbps: task.resource_requirements.network_bandwidth_mbps,
435            gpu_allocation: if task.resource_requirements.requires_gpu { Some(50.0) } else { None },
436            storage_io_mbps: task.resource_requirements.storage_io_mbps,
437        })
438    }
439
440    /// Execute task implementation (simplified)
441    fn execute_task_impl(
442        &self,
443        task: &BackgroundTask,
444    ) -> Result<TaskResult, Box<dyn std::error::Error>> {
445        let start_timestamp = std::time::SystemTime::now()
446            .duration_since(std::time::UNIX_EPOCH)
447            .expect("Operation failed")
448            .as_secs();
449
450        // Simulate task execution
451        std::thread::sleep(Duration::from_millis(100));
452
453        let end_timestamp = std::time::SystemTime::now()
454            .duration_since(std::time::UNIX_EPOCH)
455            .expect("Operation failed")
456            .as_secs();
457
458        Ok(TaskResult {
459            task_id: task.task_id.clone(),
460            status: TaskStatus::Completed,
461            start_timestamp,
462            end_timestamp: Some(end_timestamp),
463            execution_time_seconds: (end_timestamp - start_timestamp) as f64,
464            resource_usage: TaskResourceUsage {
465                peak_cpu_percent: 25.0,
466                avg_cpu_percent: 20.0,
467                peak_memory_mb: 100,
468                avg_memory_mb: 80,
469                network_data_mb: 1.0,
470                storage_io_mb: 0.5,
471                gpu_usage_percent: None,
472                battery_consumption_mah: 5.0,
473            },
474            output_data: None,
475            error_info: None,
476            performance_metrics: TaskPerformanceMetrics {
477                throughput_ops_per_second: 10.0,
478                latency_percentiles: LatencyPercentiles {
479                    p50_ms: 50.0,
480                    p90_ms: 80.0,
481                    p95_ms: 90.0,
482                    p99_ms: 100.0,
483                    max_ms: 120.0,
484                },
485                error_rate_percent: 0.0,
486                resource_efficiency_score: 85.0,
487                completion_rate_percent: 100.0,
488            },
489            quality_metrics: None,
490        })
491    }
492
493    /// Get running tasks status
494    pub fn get_running_tasks(&self) -> Vec<(String, TaskStatus, f32)> {
495        self.running_tasks
496            .lock()
497            .expect("Operation failed")
498            .iter()
499            .map(|(id, context)| (id.clone(), context.status, context.progress))
500            .collect()
501    }
502
503    /// Get completed tasks results
504    pub fn get_completed_tasks(&self) -> Vec<TaskResult> {
505        self.completed_tasks.lock().expect("Operation failed").clone()
506    }
507}
508
509impl Default for BackgroundExecutionContext {
510    fn default() -> Self {
511        Self {
512            available_cpu_percent: 50,
513            available_memory_mb: 512,
514            available_network_mbps: 10.0,
515            battery_level_percent: 80,
516            thermal_level: crate::lifecycle::config::ThermalLevel::Normal,
517            network_connected: true,
518            user_present: true,
519            system_load: 0.5,
520        }
521    }
522}
523
524impl TaskRegistry {
525    /// Create new task registry
526    pub fn new() -> Self {
527        Self {
528            registered_tasks: HashMap::new(),
529            task_templates: HashMap::new(),
530        }
531    }
532
533    /// Register a task template
534    pub fn register_task_template(&mut self, task_type: TaskType, template: BackgroundTask) {
535        self.task_templates.insert(task_type, template);
536    }
537
538    /// Create task from template
539    pub fn create_task_from_template(
540        &self,
541        task_type: TaskType,
542        task_id: String,
543    ) -> Option<BackgroundTask> {
544        self.task_templates.get(&task_type).map(|template| {
545            let mut task = template.clone();
546            task.task_id = task_id;
547            task
548        })
549    }
550
551    /// Get all registered tasks by type
552    pub fn get_tasks_by_type(&self, task_type: TaskType) -> Vec<&BackgroundTask> {
553        self.registered_tasks
554            .get(&task_type)
555            .map(|tasks| tasks.iter().collect())
556            .unwrap_or_default()
557    }
558}
559
560impl Default for TaskRegistry {
561    fn default() -> Self {
562        Self::new()
563    }
564}
565
566impl SchedulingStrategy {
567    /// Get priority order for scheduling (lower number = higher priority)
568    pub fn priority_order(&self) -> u8 {
569        match self {
570            SchedulingStrategy::Immediate => 0,
571            SchedulingStrategy::NetworkOptimal => 1,
572            SchedulingStrategy::BatteryOptimal => 2,
573            SchedulingStrategy::ThermalOptimal => 3,
574            SchedulingStrategy::UserIdle => 4,
575            SchedulingStrategy::OpportunisticAgg => 5,
576            SchedulingStrategy::Deferred => 6,
577        }
578    }
579}
580
581impl Default for ResourceRequirements {
582    fn default() -> Self {
583        Self {
584            min_cpu_percent: 10,
585            max_cpu_percent: 50,
586            min_memory_mb: 50,
587            max_memory_mb: 200,
588            network_bandwidth_mbps: None,
589            requires_gpu: false,
590            storage_io_mbps: None,
591            estimated_execution_time_seconds: 30,
592        }
593    }
594}
595
596impl Default for ExecutionConstraints {
597    fn default() -> Self {
598        Self {
599            max_execution_time_seconds: 300, // 5 minutes
600            retry_attempts: 3,
601            retry_delay_seconds: 5,
602            requires_network: false,
603            min_battery_percent: 20,
604            max_thermal_level: crate::lifecycle::config::ThermalLevel::Moderate,
605            background_eligible: true,
606            requires_user_presence: false,
607        }
608    }
609}