qualia_core_db/inference/ambient_orchestration/
scheduler.rs1use super::*;
4use std::time::Instant;
5
6pub struct TaskScheduler {
8 scheduling_policy: SchedulingPolicy,
9 task_queue: TaskQueue,
10 execution_history: Vec<TaskExecutionRecord>,
11}
12
13pub struct TaskQueue {
15 pending_tasks: Vec<Task>,
16 running_tasks: Vec<Task>,
17 completed_tasks: Vec<Task>,
18}
19
20impl TaskScheduler {
21 pub fn new() -> Self {
23 Self {
24 scheduling_policy: SchedulingPolicy::Adaptive,
25 task_queue: TaskQueue::new(),
26 execution_history: Vec::new(),
27 }
28 }
29
30 pub fn submit_task(&mut self, task: Task) -> Result<(), AmbientError> {
32 self.task_queue.pending_tasks.push(task);
33 self.sort_pending();
35 Ok(())
36 }
37
38 fn sort_pending(&mut self) {
40 match self.scheduling_policy {
41 SchedulingPolicy::Fifo => {
42 }
44 SchedulingPolicy::Priority => {
45 self.task_queue
47 .pending_tasks
48 .sort_by(|a, b| b.priority.cmp(&a.priority));
49 }
50 SchedulingPolicy::ShortestJobFirst => {
51 self.task_queue
53 .pending_tasks
54 .sort_by(|a, b| a.estimated_duration.cmp(&b.estimated_duration));
55 }
56 SchedulingPolicy::Deadline => {
57 self.task_queue
59 .pending_tasks
60 .sort_by(|a, b| match (a.deadline, b.deadline) {
61 (Some(da), Some(db)) => da.cmp(&db),
62 (Some(_), None) => std::cmp::Ordering::Less,
63 (None, Some(_)) => std::cmp::Ordering::Greater,
64 (None, None) => std::cmp::Ordering::Equal,
65 });
66 }
67 SchedulingPolicy::Adaptive => {
68 self.task_queue.pending_tasks.sort_by(|a, b| {
70 b.priority
71 .cmp(&a.priority)
72 .then_with(|| a.estimated_duration.cmp(&b.estimated_duration))
73 });
74 }
75 }
76 }
77
78 pub fn get_pending_tasks(&self) -> Vec<Task> {
80 self.task_queue.pending_tasks.clone()
81 }
82
83 pub fn get_pending_tasks_into(&self, out: &mut [TaskHandle]) -> Result<usize, AmbientError> {
84 if out.len() < self.task_queue.pending_tasks.len() {
85 return Err(AmbientError::InsufficientResources(
86 "task output buffer full".to_string(),
87 ));
88 }
89
90 for (index, task) in self.task_queue.pending_tasks.iter().enumerate() {
91 out[index] = TaskHandle {
92 task_id_hash: crate::q_hash(&task.task_id),
93 task_type: task.task_type.clone(),
94 priority: task.priority.clone(),
95 compute_units: task.resource_requirements.compute_units,
96 memory: task.resource_requirements.memory,
97 };
98 }
99
100 Ok(self.task_queue.pending_tasks.len())
101 }
102
103 pub fn dispatch_next(&mut self) -> Option<Task> {
106 let task = self.task_queue.pending_tasks.pop()?;
107 self.task_queue.running_tasks.push(task.clone());
108 Some(task)
109 }
110
111 pub fn complete_task(
113 &mut self,
114 task_id: &str,
115 device_id: &str,
116 success: bool,
117 usage: ResourceUsage,
118 ) {
119 if let Some(pos) = self
121 .task_queue
122 .running_tasks
123 .iter()
124 .position(|t| t.task_id == task_id)
125 {
126 let task = self.task_queue.running_tasks.remove(pos);
127 self.task_queue.completed_tasks.push(task.clone());
128
129 self.execution_history.push(TaskExecutionRecord {
131 task_id: task.task_id.clone(),
132 device_id: device_id.to_string(),
133 start_time: Instant::now() - task.estimated_duration,
134 end_time: Instant::now(),
135 actual_duration: task.estimated_duration,
136 success,
137 resource_usage: usage,
138 });
139
140 if self.execution_history.len() > 500 {
142 let drop = self.execution_history.len() - 500;
143 self.execution_history.drain(0..drop);
144 }
145 if self.task_queue.completed_tasks.len() > 200 {
147 let drop = self.task_queue.completed_tasks.len() - 200;
148 self.task_queue.completed_tasks.drain(0..drop);
149 }
150 }
151 }
152
153 pub fn running_count(&self) -> usize {
155 self.task_queue.running_tasks.len()
156 }
157
158 pub fn completed_count(&self) -> usize {
160 self.task_queue.completed_tasks.len()
161 }
162
163 pub fn recent_history(&self, n: usize) -> &[TaskExecutionRecord] {
165 let start = self.execution_history.len().saturating_sub(n);
166 &self.execution_history[start..]
167 }
168
169 pub fn set_policy(&mut self, policy: SchedulingPolicy) {
171 self.scheduling_policy = policy;
172 self.sort_pending();
173 }
174}
175
176impl TaskQueue {
177 pub fn new() -> Self {
178 Self {
179 pending_tasks: Vec::new(),
180 running_tasks: Vec::new(),
181 completed_tasks: Vec::new(),
182 }
183 }
184}