use std::{collections::HashMap, sync::Arc};
use crate::tasks::{error::TaskError, validator::ConfigValidator};
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, PartialEq)]
pub struct TaskConfig {
pub task_id: Option<String>,
pub command: String,
pub args: Option<Vec<String>>,
pub working_dir: Option<String>,
pub env: Option<HashMap<String, String>>,
pub timeout_ms: Option<u64>,
pub enable_stdin: Option<bool>,
pub ready_indicator: Option<String>,
pub ready_indicator_source: Option<StreamSource>,
#[cfg(feature = "process-group")]
pub use_process_group: Option<bool>,
}
pub type SharedTaskConfig = Arc<TaskConfig>;
impl Default for TaskConfig {
fn default() -> Self {
TaskConfig {
task_id: None,
command: String::new(),
args: None,
working_dir: None,
env: None,
timeout_ms: None,
enable_stdin: Some(false),
ready_indicator: None,
ready_indicator_source: Some(StreamSource::Stdout),
#[cfg(feature = "process-group")]
use_process_group: Some(true),
}
}
}
impl TaskConfig {
pub fn new(command: impl Into<String>) -> Self {
TaskConfig {
command: command.into(),
..Default::default()
}
}
pub fn task_id(mut self, id: impl Into<String>) -> Self {
self.task_id = Some(id.into());
self
}
#[must_use]
pub fn args<I, S>(mut self, args: I) -> Self
where
I: IntoIterator<Item = S>,
S: Into<String>,
{
self.args = Some(args.into_iter().map(Into::into).collect());
self
}
#[must_use]
pub fn working_dir(mut self, dir: impl Into<String>) -> Self {
self.working_dir = Some(dir.into());
self
}
#[must_use]
pub fn env<K, V, I>(mut self, env: I) -> Self
where
K: Into<String>,
V: Into<String>,
I: IntoIterator<Item = (K, V)>,
{
self.env = Some(env.into_iter().map(|(k, v)| (k.into(), v.into())).collect());
self
}
#[must_use]
pub fn timeout_ms(mut self, timeout: u64) -> Self {
self.timeout_ms = Some(timeout);
self
}
#[must_use]
pub fn enable_stdin(mut self, b: bool) -> Self {
self.enable_stdin = Some(b);
self
}
#[must_use]
pub fn ready_indicator(mut self, indicator: impl Into<String>) -> Self {
self.ready_indicator = Some(indicator.into());
self
}
#[must_use]
pub fn ready_indicator_source(mut self, source: StreamSource) -> Self {
self.ready_indicator_source = Some(source);
self
}
#[must_use]
#[cfg(feature = "process-group")]
pub fn use_process_group(mut self, enabled: bool) -> Self {
self.use_process_group = Some(enabled);
self
}
pub fn validate(&self) -> Result<(), TaskError> {
ConfigValidator::validate_command(&self.command)?;
if let Some(ready_indicator) = &self.ready_indicator {
ConfigValidator::validate_ready_indicator(ready_indicator)?;
}
if let Some(args) = &self.args {
ConfigValidator::validate_args(args)?;
}
if let Some(dir) = &self.working_dir {
ConfigValidator::validate_working_dir(dir)?;
}
if let Some(env) = &self.env {
ConfigValidator::validate_env_vars(env)?;
}
if let Some(timeout) = &self.timeout_ms {
ConfigValidator::validate_timeout(timeout)?;
}
Ok(())
}
}
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "lowercase"))]
#[derive(Debug, Clone, PartialEq)]
pub enum StreamSource {
Stdout = 0,
Stderr = 1,
}
impl Default for StreamSource {
fn default() -> Self {
Self::Stdout
}
}