1use anyhow::Result;
7use tracing::debug;
8
9use crate::jobstore::{JobDir, resolve_root};
10use crate::schema::{Response, WaitData};
11
12#[derive(Debug)]
14pub struct WaitOpts<'a> {
15 pub job_id: &'a str,
16 pub root: Option<&'a str>,
17 pub poll_ms: u64,
19 pub until: u64,
22 pub forever: bool,
24}
25
26impl<'a> Default for WaitOpts<'a> {
27 fn default() -> Self {
28 WaitOpts {
29 job_id: "",
30 root: None,
31 poll_ms: 200,
32 until: 30_000,
33 forever: false,
34 }
35 }
36}
37
38pub fn execute(opts: WaitOpts) -> Result<()> {
40 let root = resolve_root(opts.root);
41 let job_dir = JobDir::open(&root, opts.job_id)?;
42
43 let poll = std::time::Duration::from_millis(opts.poll_ms);
44 let deadline = if opts.forever {
45 None
46 } else {
47 Some(std::time::Instant::now() + std::time::Duration::from_millis(opts.until))
48 };
49
50 loop {
51 let state = job_dir.read_state()?;
52 debug!(job_id = %opts.job_id, state = ?state.status(), "wait poll");
53
54 if !state.status().is_non_terminal() {
55 let response = Response::new(
56 "wait",
57 WaitData {
58 job_id: job_dir.job_id.clone(),
59 state: state.status().as_str().to_string(),
60 exit_code: state.exit_code(),
61 },
62 );
63 response.print();
64 return Ok(());
65 }
66
67 if let Some(dl) = deadline
68 && std::time::Instant::now() >= dl
69 {
70 let response = Response::new(
72 "wait",
73 WaitData {
74 job_id: job_dir.job_id.clone(),
75 state: state.status().as_str().to_string(),
76 exit_code: None,
77 },
78 );
79 response.print();
80 return Ok(());
81 }
82
83 std::thread::sleep(poll);
84 }
85}