use crate::Result;
use crate::daemon_id::DaemonId;
use crate::ipc::batch::{StartOptions, update_job_with_result};
use crate::ipc::client::IpcClient;
use crate::pitchfork_toml::PitchforkToml;
use miette::ensure;
use std::sync::Arc;
#[derive(Debug, clap::Args)]
#[clap(
verbatim_doc_comment,
long_about = "\
Restarts a daemon (stops then starts it)
Equivalent to 'start --force' - stops the daemon (SIGTERM) then starts it again
from the pitchfork.toml configuration with dependency resolution.
Examples:
pitchfork restart api Restart a single daemon
pitchfork restart api worker Restart multiple daemons
pitchfork restart --group backend Restart all daemons in the 'backend' group
pitchfork restart --all Restart all running daemons
pitchfork restart -l Restart all local daemons in pitchfork.toml
pitchfork restart -g Restart all global daemons in config.toml
pitchfork restart api --delay 5 Wait 5 seconds for daemon to be ready"
)]
pub struct Restart {
#[clap(
conflicts_with = "local",
conflicts_with = "global",
conflicts_with = "all"
)]
id: Vec<String>,
#[clap(
long,
value_name = "GROUP",
conflicts_with = "local",
conflicts_with = "global",
conflicts_with = "all"
)]
group: Option<String>,
#[clap(long, short, conflicts_with = "local", conflicts_with = "global")]
all: bool,
#[clap(
long,
short = 'l',
visible_alias = "all-local",
conflicts_with = "all",
conflicts_with = "global"
)]
local: bool,
#[clap(
long,
short = 'g',
visible_alias = "all-global",
conflicts_with = "local",
conflicts_with = "all"
)]
global: bool,
#[clap(long)]
delay: Option<u64>,
#[clap(long)]
output: Option<String>,
#[clap(long)]
http: Option<String>,
#[clap(long)]
port: Option<u16>,
#[clap(long)]
cmd: Option<String>,
#[clap(short, long)]
quiet: bool,
}
impl Restart {
pub async fn run(&self) -> Result<()> {
ensure!(
self.local || self.global || self.all || !self.id.is_empty() || self.group.is_some(),
"At least one daemon ID, --group, or one of --all / --local / --global must be provided"
);
let ipc = Arc::new(IpcClient::connect(true).await?);
let ids: Vec<DaemonId> = if self.all {
ipc.get_running_daemons().await?
} else if self.global || self.local {
ipc.get_running_configured_daemons(self.global).await?
} else {
PitchforkToml::resolve_ids_and_group(&self.id, self.group.as_deref())?
};
if ids.is_empty() {
warn!("No daemons to restart");
return Ok(());
}
let opts = StartOptions {
force: true, delay: self.delay,
output: self.output.clone(),
http: self.http.clone(),
port: self.port,
cmd: self.cmd.clone(),
quiet: self.quiet,
..Default::default()
};
let result = ipc.start_daemons(&ids, opts).await?;
for update in &result.pending_job_updates {
update_job_with_result(update.job.as_deref(), &update.id, &update.run_result);
}
clx::progress::stop();
clx::progress::clear_jobs();
if result.any_failed {
std::process::exit(1);
}
Ok(())
}
}