use std::{collections::HashMap, path::PathBuf};
use chrono::prelude::*;
use serde_derive::{Deserialize, Serialize};
use strum_macros::Display;
use crate::state::PUEUE_DEFAULT_GROUP;
#[derive(PartialEq, Eq, Clone, Debug, Display, Serialize, Deserialize)]
pub enum TaskStatus {
Queued,
Stashed { enqueue_at: Option<DateTime<Local>> },
Running,
Paused,
Done(TaskResult),
Locked,
}
#[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,
#[serde(default = "Local::now")]
pub created_at: DateTime<Local>,
#[serde(default = "Default::default")]
pub enqueued_at: Option<DateTime<Local>>,
pub original_command: String,
pub command: String,
pub path: PathBuf,
pub envs: HashMap<String, String>,
pub group: String,
pub dependencies: Vec<usize>,
#[serde(default = "Default::default")]
pub priority: i32,
pub label: Option<String>,
pub status: TaskStatus,
pub prev_status: TaskStatus,
pub start: Option<DateTime<Local>>,
pub end: Option<DateTime<Local>>,
}
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(),
enqueued_at: None,
original_command: original_command.clone(),
command: original_command,
path,
envs,
group,
dependencies,
priority,
label,
status: starting_status.clone(),
prev_status: starting_status,
start: None,
end: None,
}
}
pub fn from_task(task: &Task) -> Task {
Task {
id: 0,
created_at: Local::now(),
enqueued_at: None,
original_command: task.original_command.clone(),
command: task.command.clone(),
path: task.path.clone(),
envs: task.envs.clone(),
group: task.group.clone(),
dependencies: Vec::new(),
priority: 0,
label: task.label.clone(),
status: TaskStatus::Queued,
prev_status: TaskStatus::Queued,
start: None,
end: None,
}
}
pub fn is_running(&self) -> bool {
matches!(self.status, TaskStatus::Running | 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(_)
}
)
}
pub fn set_default_group(&mut self) {
self.group = String::from(PUEUE_DEFAULT_GROUP);
}
pub fn is_in_default_group(&self) -> bool {
self.group.eq(PUEUE_DEFAULT_GROUP)
}
}
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("prev_status", &self.prev_status)
.field("start", &self.start)
.field("end", &self.end)
.field("priority", &self.priority)
.finish()
}
}