use std::{collections::HashMap, path::PathBuf};
use chrono::prelude::*;
use serde::{Deserialize, Serialize};
use strum::Display;
#[derive(PartialEq, Eq, Clone, Debug, Display, Serialize, Deserialize)]
pub enum TaskStatus {
Locked { previous_status: Box<TaskStatus> },
Stashed { enqueue_at: Option<DateTime<Local>> },
Queued { enqueued_at: DateTime<Local> },
Running {
enqueued_at: DateTime<Local>,
start: DateTime<Local>,
},
Paused {
enqueued_at: DateTime<Local>,
start: DateTime<Local>,
},
Done {
enqueued_at: DateTime<Local>,
start: DateTime<Local>,
end: DateTime<Local>,
result: TaskResult,
},
}
#[derive(PartialEq, Eq, Clone, Debug, Display, Serialize, Deserialize)]
pub enum TaskResult {
Success,
Failed(i32),
FailedToSpawn(String),
Killed,
Errored,
DependencyFailed,
}
#[derive(PartialEq, Eq, Clone, Deserialize, Serialize)]
pub struct Task {
pub id: usize,
pub created_at: DateTime<Local>,
pub original_command: String,
pub command: String,
pub path: PathBuf,
pub envs: HashMap<String, String>,
pub group: String,
pub dependencies: Vec<usize>,
pub priority: i32,
pub label: Option<String>,
pub status: TaskStatus,
}
impl Task {
#[allow(clippy::too_many_arguments)]
pub fn new(
original_command: String,
path: PathBuf,
envs: HashMap<String, String>,
group: String,
starting_status: TaskStatus,
dependencies: Vec<usize>,
priority: i32,
label: Option<String>,
) -> Task {
Task {
id: 0,
created_at: Local::now(),
original_command: original_command.clone(),
command: original_command,
path,
envs,
group,
dependencies,
priority,
label,
status: starting_status.clone(),
}
}
pub fn start_and_end(&self) -> (Option<DateTime<Local>>, Option<DateTime<Local>>) {
match self.status {
TaskStatus::Running { start, .. } => (Some(start), None),
TaskStatus::Paused { start, .. } => (Some(start), None),
TaskStatus::Done { start, end, .. } => (Some(start), Some(end)),
_ => (None, None),
}
}
pub fn is_running(&self) -> bool {
matches!(
self.status,
TaskStatus::Running { .. } | TaskStatus::Paused { .. }
)
}
pub fn is_paused(&self) -> bool {
matches!(self.status, TaskStatus::Paused { .. })
}
pub fn is_done(&self) -> bool {
matches!(self.status, TaskStatus::Done { .. })
}
pub fn failed(&self) -> bool {
match &self.status {
TaskStatus::Done { result, .. } => !matches!(result, TaskResult::Success),
_ => false,
}
}
pub fn is_stashed(&self) -> bool {
matches!(self.status, TaskStatus::Stashed { .. })
}
pub fn is_queued(&self) -> bool {
matches!(
self.status,
TaskStatus::Queued { .. }
| TaskStatus::Stashed {
enqueue_at: Some(_)
}
)
}
}
impl std::fmt::Debug for Task {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Task")
.field("id", &self.id)
.field("original_command", &self.original_command)
.field("command", &self.command)
.field("path", &self.path)
.field("envs", &"hidden")
.field("group", &self.group)
.field("dependencies", &self.dependencies)
.field("label", &self.label)
.field("status", &self.status)
.field("priority", &self.priority)
.finish()
}
}