jocker_lib/
stop.rs

1use std::sync::Arc;
2
3use tokio::task::JoinSet;
4
5use crate::{
6    common::{Exec, Process, ProcessState},
7    error::Result,
8    state::State,
9};
10
11#[derive(Clone, Debug, Default, PartialEq)]
12pub struct StopArgs {
13    pub kill: bool,
14    pub processes: Vec<String>,
15}
16
17pub struct Stop {
18    args: StopArgs,
19    state: Arc<State>,
20}
21
22impl Stop {
23    pub fn new(args: StopArgs, state: Arc<State>) -> Self {
24        Stop { args, state }
25    }
26}
27
28impl Exec<()> for Stop {
29    async fn exec(&self) -> Result<()> {
30        let processes = self.state.filter_processes(&self.args.processes).await?;
31        let mut handles = JoinSet::new();
32        for process in processes {
33            let state = self.state.clone();
34            handles.spawn(run(state, process, self.args.clone()));
35        }
36
37        while let Some(res) = handles.join_next().await {
38            match res {
39                Err(e) => println!("Error while stopping process: {e}"),
40                Ok(ok) => {
41                    if let Err(ee) = ok {
42                        println!("Error while stopping process inner: {ee}")
43                    }
44                }
45            }
46        }
47
48        Ok(())
49    }
50}
51
52async fn run(state: Arc<State>, process: Process, args: StopArgs) -> Result<()> {
53    let process_name = process.name().to_string();
54    if process.state == ProcessState::Stopped {
55        println!("Process is already stopped: {process_name}");
56        return Ok(());
57    }
58    if let Some(pid) = process.pid {
59        println!("Stopping process {process_name} ...");
60        state.scheduler().stop(pid, args.kill).await?;
61    }
62    state
63        .set_state(&process_name, ProcessState::Stopped)
64        .await?;
65    state.set_pid(&process_name, None).await?;
66    println!("Process {process_name} stopped");
67    Ok(())
68}