tcrm_task/tasks/
control.rs

1use std::time::SystemTime;
2
3use crate::tasks::{
4    error::TaskError,
5    event::TaskTerminateReason,
6    state::{ProcessState, TaskState},
7};
8
9/// Trait for controlling process execution.
10///
11/// This trait provides methods to control the lifecycle of a running process,
12/// including termination and signal handling.
13pub trait TaskControl {
14    /// Terminates the task with the specified reason.
15    ///
16    /// # Arguments
17    ///
18    /// * `reason` - The reason for termination
19    ///
20    /// # Returns
21    ///
22    /// * `Ok(())` - If the termination signal was sent successfully
23    /// * `Err(TaskError)` - If the task is already finished or termination fails
24    ///
25    /// # Example
26    ///
27    /// ```rust
28    /// use tcrm_task::tasks::control::TaskControl;
29    /// use tcrm_task::tasks::event::TaskTerminateReason;
30    /// use tcrm_task::tasks::config::TaskConfig;
31    /// use tcrm_task::tasks::tokio::executor::TaskExecutor;
32    /// use tokio::sync::mpsc;
33    ///
34    /// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
35    /// let config = TaskConfig::new("echo".to_string());
36    /// let (tx, _rx) = mpsc::channel(100);
37    /// let mut task = TaskExecutor::new(config, tx);
38    /// task.terminate_task(TaskTerminateReason::UserRequested)?;
39    /// # Ok(())
40    /// # }
41    /// ```
42    fn terminate_task(&mut self, reason: TaskTerminateReason) -> Result<(), TaskError>;
43
44    /// Sends a signal to the task process.
45    ///
46    /// # Arguments
47    ///
48    /// * `signal` - The signal to send to the process
49    ///
50    /// # Returns
51    ///
52    /// * `Ok(())` - If the signal was sent successfully
53    /// * `Err(TaskError)` - If signal sending fails
54    #[cfg(all(feature = "signal", unix))]
55    fn send_signal(&self, signal: nix::sys::signal::Signal) -> Result<(), TaskError>;
56}
57/// Trait for retrieving task status information.
58///
59/// This trait provides methods to query the current state and runtime
60/// information of a task.
61pub trait TaskStatusInfo {
62    /// Gets the current state of the task.
63    ///
64    /// # Returns
65    ///
66    /// The current `TaskState` of the task
67    fn get_task_state(&self) -> TaskState;
68
69    /// Gets the current state of the process.
70    ///
71    /// # Returns
72    ///
73    /// The current `ProcessState` of the process
74    #[cfg(feature = "process-control")]
75    fn get_process_state(&self) -> ProcessState;
76
77    /// Gets the process ID of the running task.
78    ///
79    /// # Returns
80    ///
81    /// * `Some(u32)` - The process ID if the task is running
82    /// * `None` - If process hasn't started yet or has finished
83    fn get_process_id(&self) -> Option<u32>;
84
85    /// Gets the creation timestamp of the task.
86    ///
87    /// # Returns
88    ///
89    /// The `SystemTime` when the task was created
90    fn get_create_at(&self) -> SystemTime;
91
92    /// Gets the timestamp when the task started running.
93    ///
94    /// # Returns
95    ///
96    /// * `Some(SystemTime)` - When the task started running
97    /// * `None` - If the task hasn't started yet
98    fn get_running_at(&self) -> Option<SystemTime>;
99
100    /// Gets the timestamp when the task finished.
101    ///
102    /// # Returns
103    ///
104    /// * `Some(SystemTime)` - When the task finished
105    /// * `None` - If the task is still running or hasn't started
106    fn get_finished_at(&self) -> Option<SystemTime>;
107
108    /// Gets the exit code of the finished task.
109    ///
110    /// # Returns
111    ///
112    /// * `Some(i32)` - The exit code if the task has finished
113    /// * `None` - If the task is still running or hasn't started
114    fn get_exit_code(&self) -> Option<i32>;
115
116    /// Gets the last received signal (if any) from the process.
117    ///
118    /// # Returns
119    ///
120    /// * `Some(i32)` - The last signal number if available
121    /// * `None` - If no signal has been received or not applicable
122    #[cfg(unix)]
123    fn get_last_signal_code(&self) -> Option<nix::sys::signal::Signal>;
124
125    /// Gets all information about the task.
126    ///
127    /// This is a convenience method that collects all status information
128    /// into a single structure.
129    ///
130    /// # Returns
131    ///
132    /// A `TaskInformation` struct containing all task status data
133    ///
134    /// # Example
135    ///
136    /// ```rust
137    /// use tcrm_task::tasks::control::TaskStatusInfo;
138    /// use tcrm_task::tasks::config::TaskConfig;
139    /// use tcrm_task::tasks::tokio::executor::TaskExecutor;
140    /// use tokio::sync::mpsc;
141    ///
142    /// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
143    /// let config = TaskConfig::new("echo".to_string());
144    /// let (tx, _rx) = mpsc::channel(100);
145    /// let task = TaskExecutor::new(config, tx);
146    /// let info = task.get_information();
147    /// println!("Task state: {:?}", info.task_state);
148    /// if let Some(pid) = info.process_id {
149    ///     println!("Process ID: {}", pid);
150    /// }
151    /// # Ok(())
152    /// # }
153    /// ```
154    fn get_information(&self) -> TaskInformation {
155        TaskInformation {
156            task_state: self.get_task_state(),
157            #[cfg(feature = "process-control")]
158            process_state: self.get_process_state(),
159            process_id: self.get_process_id(),
160            created_at: self.get_create_at(),
161            running_at: self.get_running_at(),
162            finished_at: self.get_finished_at(),
163            exit_code: self.get_exit_code(),
164            #[cfg(unix)]
165            last_signal: self.get_last_signal_code(),
166        }
167    }
168}
169
170/// Task status information.
171///
172/// This structure contains all available information about a task's
173/// current state.
174#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
175#[derive(Debug, PartialEq)]
176pub struct TaskInformation {
177    /// Current state of the task
178    pub task_state: TaskState,
179    /// Current state of the process
180    #[cfg(feature = "process-control")]
181    pub process_state: ProcessState,
182    /// Process ID if the task is running
183    pub process_id: Option<u32>,
184    /// When the task was created
185    pub created_at: SystemTime,
186    /// When the task started running (if it has started)
187    pub running_at: Option<SystemTime>,
188    /// When the task finished (if it has finished)
189    pub finished_at: Option<SystemTime>,
190    /// Exit code of the task (if it has finished)
191    pub exit_code: Option<i32>,
192
193    #[cfg(unix)]
194    /// Last received signal (if any) from process::ExitStatus
195    ///
196    /// Note: This is stored as the raw signal number (i32) for serde compatibility.
197    /// Use `nix::sys::signal::Signal::try_from()` to convert back to Signal enum.
198    #[cfg_attr(
199        feature = "serde",
200        serde(
201            serialize_with = "crate::tasks::signal::serialize_signal",
202            deserialize_with = "crate::tasks::signal::deserialize_signal"
203        )
204    )]
205    pub last_signal: Option<nix::sys::signal::Signal>,
206}