use std::time::Duration;
use indicatif::{ProgressBar, ProgressStyle};
use crate::client::{formation_path, CellosClient};
use crate::exit::{CtlError, CtlResult};
use crate::model::Formation;
const POLL_INTERVAL: Duration = Duration::from_millis(1500);
pub async fn status(client: &CellosClient, name: &str, timeout_secs: Option<u64>) -> CtlResult<()> {
let bar = ProgressBar::new_spinner();
bar.set_style(
ProgressStyle::with_template("{spinner} {wide_msg}")
.unwrap_or_else(|_| ProgressStyle::default_spinner()),
);
bar.enable_steady_tick(Duration::from_millis(120));
let deadline = timeout_secs.map(|s| std::time::Instant::now() + Duration::from_secs(s));
let path = formation_path(name);
loop {
if let Some(d) = deadline {
if std::time::Instant::now() >= d {
bar.finish_and_clear();
return Err(CtlError::api(format!(
"timed out waiting for formation/{name}"
)));
}
}
let f: Formation = match client.get_json::<Formation>(&path).await {
Ok(f) => f,
Err(e) => {
bar.finish_and_clear();
return Err(e);
}
};
let state = f.state.to_ascii_uppercase();
let cells = f.cells.len();
bar.set_message(format!(
"formation/{name}: {state} ({cells} cell{s})",
s = if cells == 1 { "" } else { "s" }
));
match state.as_str() {
"COMPLETED" => {
bar.finish_and_clear();
println!("formation/{name} COMPLETED");
return Ok(());
}
"FAILED" => {
bar.finish_and_clear();
return Err(CtlError::api(format!("formation/{name} FAILED")));
}
_ => {
tokio::select! {
_ = tokio::signal::ctrl_c() => {
bar.finish_and_clear();
return Err(CtlError::usage("rollout watch cancelled"));
}
_ = tokio::time::sleep(POLL_INTERVAL) => {}
}
}
}
}
}