tutti_core/process/
mod.rs

1use futures_core::Stream;
2use std::fmt::Debug;
3use std::pin::Pin;
4use std::{path::PathBuf, time::Duration};
5
6pub mod unix;
7
8pub type BoxStream<T> = Pin<Box<dyn Stream<Item = T> + Send>>;
9
10#[derive(Clone, Debug)]
11pub struct CommandSpec {
12    pub name: String,
13    pub cmd: Vec<String>,
14    pub cwd: Option<PathBuf>,
15    pub env: Vec<(String, String)>,
16}
17
18#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
19pub struct ProcId(pub u64);
20
21pub struct Spawned {
22    pub id: ProcId,
23    pub pid: Option<u32>,
24    pub stdout: BoxStream<Vec<u8>>,
25    pub stderr: BoxStream<Vec<u8>>,
26}
27
28impl Debug for Spawned {
29    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
30        f.debug_struct("Spawned")
31            .field("id", &self.id)
32            .field("pid", &self.pid)
33            .field("stdout", &"<stream>")
34            .field("stderr", &"<stream>")
35            .finish()
36    }
37}
38
39#[async_trait::async_trait]
40pub trait ProcessManager: Send + Sync {
41    /// Spawn a new process.
42    async fn spawn(&mut self, spec: CommandSpec) -> anyhow::Result<Spawned>;
43    /// Gracefully shutdown a process.
44    async fn shutdown(&mut self, id: ProcId) -> anyhow::Result<()>;
45    /// Wait for a process to exit.
46    async fn wait(&mut self, id: ProcId, d: Duration) -> anyhow::Result<Option<i32>>;
47    /// Forcefully kill a process.
48    async fn kill(&mut self, id: ProcId) -> anyhow::Result<()>;
49}