tcrm_task/tasks/
state.rs

1/// Execution state of a task throughout its lifecycle
2///
3/// `TaskState` tracks the progression of a task from creation through completion.
4/// States transition in a defined order, enabling event-driven tasks execution.
5///
6/// # State Transitions
7///
8/// ```text
9/// Pending → Initiating → Running → [Ready] → Finished
10///                           ↘
11///                               →  Finished
12/// ```
13///
14/// The Ready state is optional and only occurs for long-running processes
15/// with a configured ready indicator.
16///
17/// # Examples
18///
19/// ## State Monitoring
20/// ```rust
21/// use tcrm_task::tasks::{config::TaskConfig, tokio::executor::TaskExecutor, state::TaskState, control::TaskStatusInfo};
22/// use tokio::sync::mpsc;
23///
24/// #[tokio::main]
25/// async fn main() {
26///     #[cfg(windows)]
27///     let config = TaskConfig::new("cmd").args(["/C", "echo", "hello"]);
28///     #[cfg(unix)]
29///     let config = TaskConfig::new("echo").args(["hello"]);
30///     
31///     let (tx, _rx) = mpsc::channel(100);
32///     let executor = TaskExecutor::new(config, tx);
33///     
34///     // Initially pending
35///     assert_eq!(executor.get_task_state(), TaskState::Pending);
36///     
37///     // After calling coordinate_start(), state will progress through:
38///     // Pending → Initiating → Running → Finished
39/// }
40/// ```
41///
42/// ## Basic State Checking
43/// ```rust
44/// use tcrm_task::tasks::{
45///     config::TaskConfig,
46///     tokio::executor::TaskExecutor,
47///     state::TaskState,
48///     control::TaskStatusInfo
49/// };
50/// use tokio::sync::mpsc;
51///
52/// #[tokio::main]
53/// async fn main() -> Result<(), Box<dyn std::error::Error>> {
54///     #[cfg(windows)]
55///     let config = TaskConfig::new("cmd").args(["/C", "echo", "hello"]);
56///     #[cfg(unix)]
57///     let config = TaskConfig::new("echo").args(["hello"]);
58///     
59///     let (tx, _rx) = mpsc::channel(100);
60///     let executor = TaskExecutor::new(config, tx);
61///
62///     // Check initial state
63///     let state = executor.get_task_state();
64///     assert_eq!(state, TaskState::Pending);
65///     println!("Task is in {:?} state", state);
66///
67///     Ok(())
68/// }
69/// ```
70#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
71#[repr(u8)]
72#[derive(Debug, Clone, Copy, PartialEq, Eq)]
73pub enum TaskState {
74    /// Task has been created but not yet started
75    ///
76    /// Initial state when `TaskSpawner` is created. The task configuration
77    /// exists but no process has been spawned yet.
78    Pending = 0,
79
80    /// Task is being initialized and validated
81    ///
82    /// Transitional state during `start_direct()` when configuration is being
83    /// validated and the process is being prepared for spawning.
84    Initiating = 1,
85
86    /// Process is running and executing
87    ///
88    /// The system process has been spawned and is actively executing.
89    /// Output events may be emitted during this state.
90    Running = 2,
91
92    /// Process is running and executing
93    ///
94    /// Only reached by long-running processes that have a ready indicator
95    /// configured. Indicates the process has completed initialization
96    /// and is ready for work (e.g., web server listening on port).
97    /// Useful when orchestrating dependent tasks.
98    Ready = 3,
99
100    /// Task execution has completed
101    ///
102    /// Final state reached when the process exits normally, is terminated,
103    /// or encounters an error. No further state transitions occur.
104    Finished = 4,
105
106    /// Invalid state (should not occur)
107    ///
108    /// This state indicates an error in state management. It should not be
109    /// possible to reach this state during normal operation.
110    ///
111    /// Internal use only.
112    Invalid = 127,
113}
114
115impl From<u8> for TaskState {
116    /// Converts a `u8` value to a `TaskState` enum.
117    ///
118    /// Returns `TaskState::Invalid` for unknown values.
119    fn from(value: u8) -> Self {
120        match value {
121            0 => TaskState::Pending,
122            1 => TaskState::Initiating,
123            2 => TaskState::Running,
124            3 => TaskState::Ready,
125            4 => TaskState::Finished,
126            _ => TaskState::Invalid,
127        }
128    }
129}
130
131impl From<TaskState> for u8 {
132    /// Converts a `TaskState` enum to its corresponding `u8` value.
133    fn from(state: TaskState) -> Self {
134        state as u8
135    }
136}
137
138/// Represents the state of a spawned process during its lifecycle.
139///
140/// `ProcessState` is used to track whether a process is running, paused, or stopped.
141#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
142#[derive(Debug, Clone, Copy, PartialEq, Eq)]
143pub enum ProcessState {
144    /// The process is not running.
145    Stopped = 0,
146
147    /// The process is running.
148    Running = 1,
149
150    /// The process is paused.
151    Pause = 2,
152
153    /// Invalid state (should not occur).
154    Invalid = 127,
155}
156
157impl From<u8> for ProcessState {
158    /// Converts a `u8` value to a `ProcessState` enum.
159    ///
160    /// Returns `ProcessState::Stopped` for unknown values.
161    fn from(value: u8) -> Self {
162        match value {
163            0 => ProcessState::Stopped,
164            1 => ProcessState::Running,
165            2 => ProcessState::Pause,
166            _ => ProcessState::Invalid,
167        }
168    }
169}
170
171impl From<ProcessState> for u8 {
172    /// Converts a `ProcessState` enum to its corresponding `u8` value.
173    fn from(state: ProcessState) -> Self {
174        state as u8
175    }
176}