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 timeout_ms: u64,
21}
22
23impl<'a> Default for WaitOpts<'a> {
24 fn default() -> Self {
25 WaitOpts {
26 job_id: "",
27 root: None,
28 poll_ms: 200,
29 timeout_ms: 0,
30 }
31 }
32}
33
34pub fn execute(opts: WaitOpts) -> Result<()> {
36 let root = resolve_root(opts.root);
37 let job_dir = JobDir::open(&root, opts.job_id)?;
38
39 let poll = std::time::Duration::from_millis(opts.poll_ms);
40 let deadline = if opts.timeout_ms > 0 {
41 Some(std::time::Instant::now() + std::time::Duration::from_millis(opts.timeout_ms))
42 } else {
43 None
44 };
45
46 loop {
47 let state = job_dir.read_state()?;
48 debug!(job_id = %opts.job_id, state = ?state.status(), "wait poll");
49
50 if !state.status().is_non_terminal() {
51 let response = Response::new(
52 "wait",
53 WaitData {
54 job_id: opts.job_id.to_string(),
55 state: state.status().as_str().to_string(),
56 exit_code: state.exit_code(),
57 },
58 );
59 response.print();
60 return Ok(());
61 }
62
63 if let Some(dl) = deadline
64 && std::time::Instant::now() >= dl
65 {
66 let response = Response::new(
68 "wait",
69 WaitData {
70 job_id: opts.job_id.to_string(),
71 state: state.status().as_str().to_string(),
72 exit_code: None,
73 },
74 );
75 response.print();
76 return Ok(());
77 }
78
79 std::thread::sleep(poll);
80 }
81}