use crate::ai::ai_performance_engine::{
AiPerformanceEngine, AiPerformanceEngineConfig, PerformanceMetrics,
};
use serde::{Deserialize, Serialize};
use std::collections::VecDeque;
use std::sync::RwLock;
use std::sync::{Arc, Mutex};
use tokio::sync::mpsc;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Task {
pub id: String,
pub task_type: TaskType,
pub estimated_duration: u64,
pub resource_requirements: ResourceRequirements,
pub priority: u32,
pub created_at: u64,
pub deadline: Option<u64>,
pub dependencies: Vec<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum TaskType {
CpuIntensive,
IoIntensive,
MemoryIntensive,
NetworkIntensive,
Mixed,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ResourceRequirements {
pub cpu: f64,
pub memory: f64,
pub concurrency: u32,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SchedulingDecision {
pub task_id: String,
pub assigned_worker: usize,
pub estimated_start_time: u64,
pub estimated_completion_time: u64,
pub allocated_resources: ResourceAllocation,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ResourceAllocation {
pub cpu_quota: f64,
pub memory_quota: f64,
pub thread_count: u32,
}
#[derive(Debug, Clone)]
pub struct WorkerState {
pub id: usize,
pub current_load: f64,
pub active_tasks: u32,
pub cpu_usage: f64,
pub memory_usage: f64,
pub avg_task_duration: u64,
pub last_active: Instant,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct IntelligentSchedulerConfig {
pub worker_count: usize,
pub max_queue_length: usize,
pub load_balance_threshold: f64,
pub prediction_window: usize,
pub auto_scaling_interval_ms: u64,
pub min_workers: usize,
pub max_workers: usize,
pub task_timeout_ms: u64,
}
impl Default for IntelligentSchedulerConfig {
fn default() -> Self {
Self {
worker_count: 4,
max_queue_length: 10000,
load_balance_threshold: 0.8,
prediction_window: 100,
auto_scaling_interval_ms: 5000,
min_workers: 2,
max_workers: 32,
task_timeout_ms: 30000,
}
}
}
pub struct IntelligentScheduler {
pub config: IntelligentSchedulerConfig,
pub ai_engine: Arc<AiPerformanceEngine>,
pub task_queue: Arc<RwLock<VecDeque<Task>>>,
pub workers: Arc<RwLock<Vec<WorkerState>>>,
decision_history: Arc<RwLock<VecDeque<SchedulingDecision>>>,
task_completion_tx: mpsc::UnboundedSender<(String, Result<(), String>)>,
task_completion_rx: Arc<Mutex<mpsc::UnboundedReceiver<(String, Result<(), String>)>>>,
stats: Arc<Mutex<SchedulerStats>>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SchedulerStats {
pub total_scheduled: u64,
pub completed_tasks: u64,
pub timeout_tasks: u64,
pub avg_wait_time: f64,
pub avg_execution_time: f64,
pub resource_utilization: f64,
pub auto_scaling_events: u64,
}
impl Default for SchedulerStats {
fn default() -> Self {
Self {
total_scheduled: 0,
completed_tasks: 0,
timeout_tasks: 0,
avg_wait_time: 0.0,
avg_execution_time: 0.0,
resource_utilization: 0.0,
auto_scaling_events: 0,
}
}
}
impl IntelligentScheduler {
pub fn new(config: IntelligentSchedulerConfig, ai_config: AiPerformanceEngineConfig) -> Self {
let (task_completion_tx, task_completion_rx) = mpsc::unbounded_channel();
let mut workers = Vec::with_capacity(config.worker_count);
for i in 0..config.worker_count {
workers.push(WorkerState {
id: i,
current_load: 0.0,
active_tasks: 0,
cpu_usage: 0.0,
memory_usage: 0.0,
avg_task_duration: 0,
last_active: std::time::Instant::now(),
});
}
Self {
config: config.clone(),
ai_engine: Arc::new(AiPerformanceEngine::new(ai_config)),
task_queue: Arc::new(RwLock::new(VecDeque::with_capacity(
config.max_queue_length,
))),
workers: Arc::new(RwLock::new(workers)),
decision_history: Arc::new(RwLock::new(VecDeque::with_capacity(
config.prediction_window,
))),
task_completion_tx,
task_completion_rx: Arc::new(Mutex::new(task_completion_rx)),
stats: Arc::new(Mutex::new(SchedulerStats::default())),
}
}
pub async fn submit_task(&self, task: Task) -> Result<(), Box<dyn std::error::Error>> {
let mut queue = self.task_queue.write().await;
if queue.len() >= self.config.max_queue_length {
return Err("任务队列已满".into());
}
queue.push_back(task.clone());
println!("任务已提交: {}, 队列长度: {}", task.id, queue.len());
self.schedule_tasks().await;
Ok(())
}
pub async fn schedule_tasks(&self) {
let mut queue = self.task_queue.write().await;
let mut workers = self.workers.write().await;
if queue.is_empty() {
return;
}
let ai_prediction: _ = self
.ai_engine
.predict_performance()
.await
.unwrap_or_else(|_| {
crate::ai::ai_performance_engine::PerformancePrediction {
predicted_execution_time: 100.0,
predicted_memory: 100.0,
predicted_throughput: 1000.0,
confidence: 0.5,
optimization_suggestions: Vec::new(),
}
});
let mut tasks: Vec<Task> = queue.drain(..).collect();
tasks.sort_by(|a, b| b.priority.cmp(&a.priority));
for task in tasks {
if let Some(worker_idx) = self
.select_best_worker(&workers, &task, &ai_prediction)
.await
{
let decision: _ =
self.create_scheduling_decision(&task, worker_idx, &workers[worker_idx]);
workers[worker_idx].current_load += self.calculate_task_load(&task);
workers[worker_idx].active_tasks += 1;
workers[worker_idx].last_active = std::time::Instant::now();
{
let mut history = self.decision_history.write().await;
history.push_back(decision);
if history.len() > self.config.prediction_window {
history.pop_front();
}
}
{
let mut stats = self.stats.lock().unwrap();
stats.total_scheduled += 1;
}
println!("任务 {} 已调度到工作线程 {}", task.id, worker_idx);
let completion_tx = self.task_completion_tx.clone();
let _worker_id = worker_idx;
let task_id = task.id.clone();
tokio::spawn(async move {
tokio::time::sleep(Duration::from_millis(task.estimated_duration)).await;
let _ = completion_tx.send((task_id, Ok(())));
});
} else {
queue.push_back(task.clone());
}
}
}
async fn select_best_worker(
&self,
workers: &[WorkerState],
task: &Task,
ai_prediction: &crate::ai::ai_performance_engine::PerformancePrediction,
) -> Option<usize> {
let mut best_worker = None;
let mut best_score = f64::MIN;
for (idx, worker) in workers.iter().enumerate() {
let load_score: _ = 1.0 - worker.current_load;
let resource_score: _ = match task.task_type {
TaskType::CpuIntensive => 1.0 - (worker.cpu_usage / 100.0),
TaskType::MemoryIntensive => 1.0 - (worker.memory_usage / 1000.0),
TaskType::IoIntensive => 0.8, TaskType::NetworkIntensive => 0.7,
TaskType::Mixed => 0.5,
};
let ai_score: _ = ai_prediction.confidence;
let score: _ = load_score * 0.4 + resource_score * 0.4 + ai_score * 0.2;
if score > best_score {
best_score = score;
best_worker = Some(idx);
}
}
if let Some(idx) = best_worker {
if workers[idx].current_load < self.config.load_balance_threshold {
best_worker
} else {
None
}
} else {
None
}
}
fn create_scheduling_decision(
&self,
task: &Task,
worker_idx: usize,
worker: &WorkerState,
) -> SchedulingDecision {
let now: _ = chrono::Utc::now().timestamp() as u64;
let estimated_start_time: _ = now;
let estimated_completion_time: _ = now + task.estimated_duration as u64;
SchedulingDecision {
task_id: task.id.clone(),
assigned_worker: worker_idx,
estimated_start_time,
estimated_completion_time,
allocated_resources: ResourceAllocation {
cpu_quota: task.resource_requirements.cpu,
memory_quota: task.resource_requirements.memory,
thread_count: task.resource_requirements.concurrency,
},
}
}
fn calculate_task_load(&self, task: &Task) -> f64 {
match task.task_type {
TaskType::CpuIntensive => task.resource_requirements.cpu / 100.0,
TaskType::MemoryIntensive => task.resource_requirements.memory / 1000.0,
TaskType::IoIntensive => 0.3,
TaskType::NetworkIntensive => 0.5,
TaskType::Mixed => 0.7,
}
}
pub async fn process_task_completions(&self) {
let mut completion_rx = self.task_completion_rx.lock().unwrap();
while let Ok((task_id, result)) = completion_rx.try_recv() {
{
let mut workers = self.workers.write().await;
for worker in &mut *workers {
if worker.active_tasks > 0 {
worker.active_tasks -= 1;
}
}
}
{
let mut stats = self.stats.lock().unwrap();
match result {
Ok(_) => stats.completed_tasks += 1,
Err(_) => stats.timeout_tasks += 1,
}
}
println!("任务完成: {}", task_id);
}
}
pub async fn auto_scaling(&self) {
let workers: _ = self.workers.read().await;
let queue: _ = self.task_queue.read().await;
let avg_load: f64 =
workers.iter().map(|w| w.current_load).sum::<f64>() / workers.len() as f64;
let queue_ratio: _ = queue.len() as f64 / self.config.max_queue_length as f64;
drop(workers);
drop(queue);
if (queue_ratio > 0.8 || avg_load > 0.8) && self.should_scale_up().await {
self.scale_up().await;
}
else if (queue_ratio < 0.2 && avg_load < 0.3) && self.should_scale_down().await {
self.scale_down().await;
}
}
async fn should_scale_up(&self) -> bool {
let workers: _ = self.workers.read().await;
workers.len() < self.config.max_workers
}
async fn should_scale_down(&self) -> bool {
let workers: _ = self.workers.read().await;
workers.len() > self.config.min_workers
}
async fn scale_up(&self) {
let mut workers = self.workers.write().await;
let new_worker_id: _ = workers.len();
workers.push(WorkerState {
id: new_worker_id,
current_load: 0.0,
active_tasks: 0,
cpu_usage: 0.0,
memory_usage: 0.0,
avg_task_duration: 0,
last_active: std::time::Instant::now(),
});
{
let mut stats = self.stats.lock().unwrap();
stats.auto_scaling_events += 1;
}
println!("扩容: 添加工作线程 {}", new_worker_id);
}
async fn scale_down(&self) {
let mut workers = self.workers.write().await;
let min_load_idx: _ = workers
.iter()
.enumerate()
.min_by(|(_, a), (_, b)| a.current_load.partial_cmp(&b.current_load).unwrap())
.map(|(idx, _)| idx)
.unwrap();
workers.remove(min_load_idx);
{
let mut stats = self.stats.lock().unwrap();
stats.auto_scaling_events += 1;
}
println!("缩容: 移除工作线程 {}", min_load_idx);
}
pub fn get_stats(&self) -> SchedulerStats {
self.stats.lock().unwrap().clone()
}
pub async fn get_queue_length(&self) -> usize {
let queue: _ = self.task_queue.read().await;
queue.len()
}
pub async fn get_worker_count(&self) -> usize {
let workers: _ = self.workers.read().await;
workers.len()
}
pub fn start_background_tasks(self: Arc<Self>) {
let _self_clone: _ = Arc::clone(self);
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::time::{Duration, Instant};
#[tokio::test]
async fn test_submit_and_schedule_task() {
let config = IntelligentSchedulerConfig::default();
let ai_config = AiPerformanceEngineConfig::default();
let scheduler = Arc::new(Mutex::new(IntelligentScheduler::new(config, ai_config)));
let task = Task {
id: "task-1".to_string(),
task_type: TaskType::CpuIntensive,
estimated_duration: 100,
resource_requirements: ResourceRequirements {
cpu: 50.0,
memory: 100.0,
concurrency: 1,
},
priority: 80,
created_at: chrono::Utc::now().timestamp() as u64,
deadline: None,
dependencies: Vec::new(),
};
scheduler.submit_task(task).await.unwrap();
let queue_length: _ = scheduler.get_queue_length().await;
assert!(queue_length > 0);
let scheduler_clone: _ = Arc::clone(scheduler);
scheduler_clone.start_background_tasks();
tokio::time::sleep(Duration::from_millis(200)).await;
let stats: _ = scheduler.get_stats();
println!("调度统计: {:?}", stats);
}
}