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}