tcrm-task 0.4.2

Task execution unit for TCRM project
Documentation
use std::sync::Arc;

use crate::tasks::{
    error::TaskError,
    event::{TaskEvent, TaskStopReason},
    state::TaskState,
    tokio::{context::TaskExecutorContext, executor::TaskExecutor},
};

impl TaskExecutor {
    /// Handles the final result of task execution.
    ///
    /// Processes the task completion, ensures proper cleanup (including
    /// process group termination if configured), and sends the final
    /// stopped event with the appropriate reason and exit code.
    ///
    /// # Arguments
    ///
    /// * `shared_context` - Shared task execution context
    /// * `event_tx` - Channel for sending task events
    pub(crate) async fn handle_result(shared_context: Arc<TaskExecutorContext>) {
        let reason = shared_context.get_stop_reason().await;
        let reason = match reason {
            Some(r) => r,
            None => {
                // This should not happen, but just in case
                let msg = "Task finished without a stop reason";
                #[cfg(feature = "tracing")]
                tracing::warn!(msg);
                TaskStopReason::Error(TaskError::Channel(msg.to_string()))
            }
        };

        // Terminate if using process groups, and the task was not terminated by handle_terminate
        #[cfg(feature = "process-group")]
        if shared_context.config.use_process_group.unwrap_or_default()
            && !matches!(reason, TaskStopReason::Terminated(_))
        {
            if let Err(e) = shared_context.group.lock().await.stop_group() {
                let msg = format!("Failed to terminate process group: {}", e);

                #[cfg(feature = "tracing")]
                tracing::error!(error=%e, "{}", msg);

                let error = TaskError::Control(msg);
                let event = TaskEvent::Error { error };
                let _ = shared_context.send_event(event).await;
            };
        }
        let time = shared_context.set_task_state(TaskState::Finished);
        let exit_code = shared_context.get_exit_code();
        shared_context.set_process_id(0);
        let event = TaskEvent::Stopped {
            exit_code,
            reason: reason,
            finished_at: time,
            #[cfg(unix)]
            signal: shared_context.get_last_signal_code(),
        };

        let _ = shared_context.send_event(event).await;
        shared_context.clear_event_tx().await;
    }
}