|
1 | | -use std::{error::Error, path::PathBuf}; |
| 1 | +use std::{error::Error, path::PathBuf, process::Stdio, thread, time::Duration}; |
2 | 2 |
|
3 | 3 | use clap::{Args, Command, Parser, Subcommand, ValueHint, builder::TypedValueParser}; |
4 | 4 | use clap_complete::{Generator, Shell, generate}; |
5 | 5 | use color_eyre::Result; |
| 6 | +use pid1::Pid1Settings; |
| 7 | +use rust_supervisor::{ChildType, Supervisor, SupervisorConfig}; |
6 | 8 | use strum::VariantNames; |
7 | 9 |
|
8 | 10 | use crate::{ |
@@ -63,6 +65,11 @@ pub enum CliCommands { |
63 | 65 | #[clap(value_enum)] |
64 | 66 | generator: Shell, |
65 | 67 | }, |
| 68 | + #[clap(about = "Execute a process/command through coman, with additional monitoring and side processes")] |
| 69 | + Exec { |
| 70 | + #[clap(trailing_var_arg = true, help = "The command to run", value_hint=ValueHint::Other)] |
| 71 | + command: Vec<String>, |
| 72 | + }, |
66 | 73 | } |
67 | 74 |
|
68 | 75 | #[derive(Subcommand, Debug)] |
@@ -372,3 +379,41 @@ fn is_bare_string(value_str: &str) -> bool { |
372 | 379 | pub fn print_completions<G: Generator>(generator: G, cmd: &mut Command) { |
373 | 380 | generate(generator, cmd, cmd.get_name().to_string(), &mut std::io::stdout()); |
374 | 381 | } |
| 382 | +pub(crate) async fn cli_exec_command(command: Vec<String>) -> Result<()> { |
| 383 | + // Pid1 takes care of proper terminating of processes and signal handling when running in a container |
| 384 | + Pid1Settings::new() |
| 385 | + .enable_log(true) |
| 386 | + .timeout(Duration::from_secs(2)) |
| 387 | + .launch() |
| 388 | + .expect("Launch failed"); |
| 389 | + |
| 390 | + let mut supervisor = Supervisor::new(SupervisorConfig::default()); |
| 391 | + supervisor.add_process("iroh-ssh", ChildType::Permanent, || { |
| 392 | + thread::spawn(|| { |
| 393 | + // iroh! |
| 394 | + }) |
| 395 | + }); |
| 396 | + supervisor.add_process("main-process", ChildType::Temporary, move || { |
| 397 | + let command = command.clone(); |
| 398 | + thread::spawn(move || { |
| 399 | + let mut child = std::process::Command::new(command[0].clone()) |
| 400 | + .args(&command[1..]) |
| 401 | + .spawn() |
| 402 | + .expect("Failed to start compute job"); |
| 403 | + child.wait().expect("Failed to wait on compute job"); |
| 404 | + }) |
| 405 | + }); |
| 406 | + |
| 407 | + let supervisor = supervisor.start_monitoring(); |
| 408 | + loop { |
| 409 | + thread::sleep(Duration::from_secs(1)); |
| 410 | + |
| 411 | + if let Some(state) = supervisor.get_process_state("main-process") { |
| 412 | + match state { |
| 413 | + rust_supervisor::ProcessState::Failed | rust_supervisor::ProcessState::Stopped => break, |
| 414 | + _ => {} |
| 415 | + } |
| 416 | + } |
| 417 | + } |
| 418 | + Ok(()) |
| 419 | +} |
0 commit comments