use chrono::{DateTime, Utc};
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct WFQConfig {
pub enabled: bool,
pub default_weight: f64,
pub min_weight: f64,
pub max_weight: f64,
}
impl Default for WFQConfig {
fn default() -> Self {
Self {
enabled: false,
default_weight: 1.0,
min_weight: 0.1,
max_weight: 10.0,
}
}
}
#[derive(Debug, Clone, Copy, serde::Serialize, serde::Deserialize)]
pub struct TaskWeight(f64);
impl TaskWeight {
pub fn new(weight: f64) -> Result<Self, String> {
if !(0.1..=10.0).contains(&weight) {
return Err(format!(
"Weight must be between 0.1 and 10.0, got {}",
weight
));
}
Ok(Self(weight))
}
pub fn value(&self) -> f64 {
self.0
}
}
impl Default for TaskWeight {
fn default() -> Self {
Self(1.0)
}
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct WFQState {
#[serde(default)]
pub weight: TaskWeight,
#[serde(default)]
pub virtual_start_time: f64,
#[serde(default)]
pub virtual_finish_time: f64,
#[serde(default)]
pub total_execution_time: f64,
}
impl Default for WFQState {
fn default() -> Self {
Self {
weight: TaskWeight::default(),
virtual_start_time: 0.0,
virtual_finish_time: 0.0,
total_execution_time: 0.0,
}
}
}
impl WFQState {
pub fn with_weight(weight: f64) -> Result<Self, String> {
Ok(Self {
weight: TaskWeight::new(weight)?,
..Default::default()
})
}
pub fn update_after_execution(
&mut self,
execution_duration_secs: f64,
global_virtual_time: f64,
) {
self.total_execution_time += execution_duration_secs;
self.virtual_start_time = global_virtual_time.max(self.virtual_finish_time);
self.virtual_finish_time =
self.virtual_start_time + (execution_duration_secs / self.weight.value());
}
pub fn finish_time(&self) -> f64 {
self.virtual_finish_time
}
}
#[derive(Debug, Clone)]
pub struct WFQTaskInfo {
pub name: String,
pub virtual_finish_time: f64,
pub weight: f64,
pub next_run_time: DateTime<Utc>,
}