#[cfg(not(feature = "scirs2"))]
use super::fallback_scirs2::*;
use super::types::*;
use std::collections::{BTreeMap, HashMap, HashSet, VecDeque};
use std::sync::{Arc, Mutex, RwLock};
use std::time::{Duration, SystemTime};
impl Clone for QuantumJobScheduler {
fn clone(&self) -> Self {
Self {
params: Arc::clone(&self.params),
job_queues: Arc::clone(&self.job_queues),
jobs: Arc::clone(&self.jobs),
backend_performance: Arc::clone(&self.backend_performance),
backends: Arc::clone(&self.backends),
running_jobs: Arc::clone(&self.running_jobs),
execution_history: Arc::clone(&self.execution_history),
user_shares: Arc::clone(&self.user_shares),
scheduler_running: Arc::clone(&self.scheduler_running),
event_sender: self.event_sender.clone(),
performance_predictor: Arc::clone(&self.performance_predictor),
resource_manager: Arc::clone(&self.resource_manager),
job_status_map: Arc::clone(&self.job_status_map),
job_config_map: Arc::clone(&self.job_config_map),
job_metrics_map: Arc::clone(&self.job_metrics_map),
}
}
}
impl PerformancePredictor {
pub(crate) fn new() -> Self {
Self {
history: VecDeque::new(),
model_params: HashMap::new(),
accuracy_metrics: HashMap::new(),
}
}
}
impl ResourceManager {
pub(crate) fn new() -> Self {
Self {
available_resources: HashMap::new(),
reservations: HashMap::new(),
utilization_history: VecDeque::new(),
}
}
}
pub fn create_high_priority_config(max_execution_time: Duration) -> JobConfig {
JobConfig {
priority: JobPriority::High,
max_execution_time,
retry_attempts: 5,
..Default::default()
}
}
pub fn create_batch_job_config() -> JobConfig {
JobConfig {
priority: JobPriority::BestEffort,
max_execution_time: Duration::from_secs(3600 * 24),
max_queue_time: None,
retry_attempts: 1,
..Default::default()
}
}
pub fn create_realtime_config() -> JobConfig {
JobConfig {
priority: JobPriority::Critical,
max_execution_time: Duration::from_secs(60),
max_queue_time: Some(Duration::from_secs(30)),
retry_attempts: 0,
..Default::default()
}
}
pub fn create_sla_aware_config(tier: SLATier) -> JobConfig {
let (priority, max_execution_time, max_queue_time, retry_attempts) = match tier {
SLATier::Gold => (
JobPriority::Critical,
Duration::from_secs(300),
Some(Duration::from_secs(60)),
5,
),
SLATier::Silver => (
JobPriority::High,
Duration::from_secs(600),
Some(Duration::from_secs(300)),
3,
),
SLATier::Bronze => (
JobPriority::Normal,
Duration::from_secs(1800),
Some(Duration::from_secs(900)),
2,
),
SLATier::Basic => (
JobPriority::Low,
Duration::from_secs(3600),
Some(Duration::from_secs(1800)),
1,
),
};
JobConfig {
priority,
max_execution_time,
max_queue_time,
retry_attempts,
..Default::default()
}
}
pub fn create_cost_optimized_config(budget_limit: f64) -> JobConfig {
JobConfig {
priority: JobPriority::BestEffort,
max_execution_time: Duration::from_secs(7200),
max_queue_time: None,
retry_attempts: 1,
cost_limit: Some(budget_limit),
preferred_backends: vec![],
..Default::default()
}
}
pub fn create_energy_efficient_config() -> JobConfig {
JobConfig {
priority: JobPriority::Low,
max_execution_time: Duration::from_secs(3600),
max_queue_time: None,
retry_attempts: 2,
tags: std::iter::once(("energy_profile".to_string(), "green".to_string())).collect(),
..Default::default()
}
}
pub fn create_research_config() -> JobConfig {
JobConfig {
priority: JobPriority::Normal,
max_execution_time: Duration::from_secs(14400),
max_queue_time: Some(Duration::from_secs(7200)),
retry_attempts: 3,
tags: [
("workload_type".to_string(), "research".to_string()),
("fault_tolerance".to_string(), "high".to_string()),
]
.into_iter()
.collect(),
..Default::default()
}
}
pub fn create_deadline_config(deadline: SystemTime) -> JobConfig {
JobConfig {
priority: JobPriority::High,
max_execution_time: Duration::from_secs(1800),
max_queue_time: Some(Duration::from_secs(300)),
retry_attempts: 2,
deadline: Some(deadline),
tags: std::iter::once((
"scheduling_type".to_string(),
"deadline_sensitive".to_string(),
))
.collect(),
..Default::default()
}
}
pub fn create_ml_training_config() -> JobConfig {
JobConfig {
priority: JobPriority::Normal,
max_execution_time: Duration::from_secs(21600),
max_queue_time: Some(Duration::from_secs(3600)),
retry_attempts: 2,
resource_requirements: ResourceRequirements {
min_qubits: 20,
max_depth: Some(1000),
min_fidelity: Some(0.95),
memory_mb: Some(16384),
cpu_cores: Some(8),
required_features: vec![
"variational_circuits".to_string(),
"parametric_gates".to_string(),
],
..Default::default()
},
tags: [
("workload_type".to_string(), "machine_learning".to_string()),
("resource_intensive".to_string(), "true".to_string()),
]
.into_iter()
.collect(),
..Default::default()
}
}
pub fn create_optimization_config() -> JobConfig {
JobConfig {
priority: JobPriority::Normal,
max_execution_time: Duration::from_secs(10800),
max_queue_time: Some(Duration::from_secs(1800)),
retry_attempts: 3,
resource_requirements: ResourceRequirements {
min_qubits: 10,
max_depth: Some(500),
min_fidelity: Some(0.90),
required_features: vec!["qaoa".to_string(), "variational_algorithms".to_string()],
..Default::default()
},
tags: [
("workload_type".to_string(), "optimization".to_string()),
("algorithm_type".to_string(), "variational".to_string()),
]
.into_iter()
.collect(),
..Default::default()
}
}
pub fn create_simulation_config(qubit_count: usize) -> JobConfig {
let (max_execution_time, memory_requirement) = match qubit_count {
1..=20 => (Duration::from_secs(3600), 4096),
21..=30 => (Duration::from_secs(7200), 8192),
31..=40 => (Duration::from_secs(14400), 16384),
_ => (Duration::from_secs(28800), 32768),
};
JobConfig {
priority: JobPriority::Low,
max_execution_time,
max_queue_time: None,
retry_attempts: 1,
resource_requirements: ResourceRequirements {
min_qubits: qubit_count,
memory_mb: Some(memory_requirement),
cpu_cores: Some(16),
required_features: vec!["high_precision".to_string(), "large_circuits".to_string()],
..Default::default()
},
tags: [
("workload_type".to_string(), "simulation".to_string()),
("qubit_count".to_string(), qubit_count.to_string()),
]
.into_iter()
.collect(),
..Default::default()
}
}
#[cfg(test)]
mod tests {
use super::*;
use quantrs2_circuit::prelude::CircuitBuilder;
#[tokio::test]
async fn test_job_scheduler_creation() {
let params = SchedulingParams::default();
let scheduler = QuantumJobScheduler::new(params);
assert!(!*scheduler
.scheduler_running
.lock()
.expect("Failed to acquire lock on scheduler_running in test"));
}
#[tokio::test]
async fn test_job_config_validation() {
let config = JobConfig::default();
assert_eq!(config.priority, JobPriority::Normal);
assert_eq!(config.retry_attempts, 3);
assert!(config.dependencies.is_empty());
}
#[tokio::test]
async fn test_priority_ordering() {
assert!(JobPriority::Critical < JobPriority::High);
assert!(JobPriority::High < JobPriority::Normal);
assert!(JobPriority::Normal < JobPriority::Low);
assert!(JobPriority::Low < JobPriority::BestEffort);
}
#[test]
fn test_job_id_creation() {
let id1 = JobId::new();
let id2 = JobId::new();
assert_ne!(id1, id2);
assert!(!id1.0.is_empty());
}
#[test]
fn test_convenience_configs() {
let high_priority = create_high_priority_config(Duration::from_secs(300));
assert_eq!(high_priority.priority, JobPriority::High);
assert_eq!(high_priority.retry_attempts, 5);
let batch = create_batch_job_config();
assert_eq!(batch.priority, JobPriority::BestEffort);
assert!(batch.max_queue_time.is_none());
let realtime = create_realtime_config();
assert_eq!(realtime.priority, JobPriority::Critical);
assert_eq!(realtime.retry_attempts, 0);
}
}