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 predictable state management
5/// and event-driven programming.
6///
7/// # State Transitions
8///
9/// ```text
10/// Pending → Initiating → Running → [Ready] → Finished
11///                             ↘
12///                               → Finished
13/// ```
14///
15/// The Ready state is optional and only occurs for long-running processes
16/// with a configured ready indicator.
17///
18/// # Examples
19///
20/// ## State Monitoring
21/// ```rust
22/// use tcrm_task::tasks::{config::TaskConfig, async_tokio::spawner::TaskSpawner, state::TaskState};
23///
24/// #[tokio::main]
25/// async fn main() {
26///     let config = TaskConfig::new("cmd").args(["/C", "echo", "hello"]);
27///     let spawner = TaskSpawner::new("test".to_string(), config);
28///     
29///     // Initially pending
30///     assert_eq!(spawner.get_state().await, TaskState::Pending);
31///     
32///     // After calling start_direct(), state will progress through:
33///     // Pending → Initiating → Running → Finished
34/// }
35/// ```
36///
37/// ## Basic State Checking
38/// ```rust
39/// use tcrm_task::tasks::{
40///     config::TaskConfig,
41///     async_tokio::spawner::TaskSpawner,
42///     state::TaskState
43/// };
44///
45/// #[tokio::main]
46/// async fn main() -> Result<(), Box<dyn std::error::Error>> {
47///     let config = TaskConfig::new("cmd").args(["/C", "echo", "hello"]);
48///     let spawner = TaskSpawner::new("demo".to_string(), config);
49///
50///     // Check initial state
51///     let state = spawner.get_state().await;
52///     assert_eq!(state, TaskState::Pending);
53///     println!("Task is in {:?} state", state);
54///
55///     Ok(())
56/// }
57/// ```
58#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
59#[derive(Debug, Clone, PartialEq)]
60pub enum TaskState {
61    /// Task has been created but not yet started
62    ///
63    /// Initial state when `TaskSpawner` is created. The task configuration
64    /// exists but no process has been spawned yet.
65    Pending,
66
67    /// Task is being initialized and validated
68    ///
69    /// Transitional state during `start_direct()` when configuration is being
70    /// validated and the process is being prepared for spawning.
71    Initiating,
72
73    /// Process is running and executing
74    ///
75    /// The system process has been spawned and is actively executing.
76    /// Output events may be emitted during this state.
77    Running,
78
79    /// Process is running and ready to accept requests
80    ///
81    /// Only reached by long-running processes that have a ready indicator
82    /// configured. Indicates the process has completed initialization
83    /// and is ready for work (e.g., web server listening on port).
84    Ready,
85
86    /// Task execution has completed
87    ///
88    /// Final state reached when the process exits normally, is terminated,
89    /// or encounters an error. No further state transitions occur.
90    Finished,
91}
92
93/// Reason for terminating a running task
94///
95/// Provides context about why a task termination was requested,
96/// enabling appropriate cleanup and response handling.
97///
98/// # Examples
99///
100/// ## Timeout Termination
101/// ```rust
102/// use tcrm_task::tasks::{
103///     config::TaskConfig,
104///     async_tokio::spawner::TaskSpawner,
105///     state::TaskTerminateReason
106/// };
107/// use tokio::sync::mpsc;
108///
109/// #[tokio::main]
110/// async fn main() -> Result<(), Box<dyn std::error::Error>> {
111///     let config = TaskConfig::new("cmd").args(["/C", "ping", "127.0.0.1", "-n", "5"]); // 5 second sleep
112///     let mut spawner = TaskSpawner::new("long-task".to_string(), config);
113///     
114///     let (tx, _rx) = mpsc::channel(100);
115///     spawner.start_direct(tx).await?;
116///     
117///     // Terminate after 1 second
118///     tokio::time::sleep(tokio::time::Duration::from_secs(1)).await;
119///     spawner.send_terminate_signal(TaskTerminateReason::Timeout).await?;
120///     
121///     Ok(())
122/// }
123/// ```
124///
125/// ## Custom Termination
126/// ```rust
127/// use tcrm_task::tasks::{
128///     config::TaskConfig,
129///     async_tokio::spawner::TaskSpawner,
130///     state::TaskTerminateReason
131/// };
132/// use tokio::sync::mpsc;
133///
134/// #[tokio::main]
135/// async fn main() -> Result<(), Box<dyn std::error::Error>> {
136///     let config = TaskConfig::new("cmd").args(["/C", "echo", "running"]);
137///     let mut spawner = TaskSpawner::new("daemon".to_string(), config);
138///     
139///     let (tx, _rx) = mpsc::channel(100);
140///     spawner.start_direct(tx).await?;
141///     
142///     // Custom shutdown reason
143///     let reason = TaskTerminateReason::Custom("User requested shutdown".to_string());
144///     spawner.send_terminate_signal(reason).await?;
145///     
146///     Ok(())
147/// }
148/// ```
149#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
150#[derive(Debug, Clone, PartialEq)]
151pub enum TaskTerminateReason {
152    /// Task exceeded its configured timeout
153    ///
154    /// The process ran longer than the `timeout_ms` specified in `TaskConfig`
155    /// and was terminated to prevent runaway processes.
156    Timeout,
157
158    /// Task was terminated during cleanup operations
159    ///
160    /// Used when terminating tasks as part of application shutdown,
161    /// resource cleanup, or dependency management.
162    Cleanup,
163
164    /// Task was terminated because its dependencies finished
165    ///
166    /// Used in task orchestration scenarios where tasks depend on
167    /// other tasks and should be terminated when dependencies complete.
168    DependenciesFinished,
169
170    /// Task was terminated for a custom application-specific reason
171    ///
172    /// Allows applications to provide specific context about why
173    /// a task was terminated beyond the standard reasons.
174    Custom(String),
175}