use std::time::{Duration, Instant};
use anyhow::{Result, bail};
use crate::interrupt;
pub fn grace_period() -> Duration {
millis_from_env("THIRDSHIFT_CI_GRACE_MS").unwrap_or(Duration::from_secs(60))
}
pub fn until<T>(mut probe: impl FnMut() -> Result<Option<T>>) -> Result<T> {
loop {
if let Some(answer) = probe()? {
return Ok(answer);
}
pause()?;
}
}
pub fn pause() -> Result<()> {
sleep(poll_interval())
}
pub fn within<T>(
limit: Duration,
mut probe: impl FnMut() -> Result<Option<T>>,
) -> Result<Option<T>> {
let deadline = Instant::now() + limit;
until(|| match probe()? {
Some(answer) => Ok(Some(Some(answer))),
None if Instant::now() >= deadline => Ok(Some(None)),
None => Ok(None),
})
}
fn poll_interval() -> Duration {
millis_from_env("THIRDSHIFT_POLL_MS").unwrap_or(Duration::from_secs(10))
}
fn millis_from_env(name: &str) -> Option<Duration> {
let millis = std::env::var(name).ok()?.parse().ok()?;
Some(Duration::from_millis(millis))
}
fn sleep(duration: Duration) -> Result<()> {
let deadline = Instant::now() + duration;
loop {
if interrupt::requested() {
bail!("interrupted");
}
let left = deadline.saturating_duration_since(Instant::now());
if left.is_zero() {
return Ok(());
}
std::thread::sleep(left.min(Duration::from_millis(100)));
}
}