thirtyfour/extensions/query/
poller.rsuse crate::support::sleep;
use std::fmt::Debug;
use std::time::{Duration, Instant};
#[async_trait::async_trait]
pub trait ElementPoller: Debug {
async fn tick(&mut self) -> bool;
}
pub trait IntoElementPoller: Debug {
fn start(&self) -> Box<dyn ElementPoller + Send + Sync>;
}
#[derive(Debug)]
pub struct ElementPollerWithTimeout {
timeout: Duration,
interval: Duration,
start: Instant,
cur_tries: u32,
}
impl ElementPollerWithTimeout {
pub fn new(timeout: Duration, interval: Duration) -> Self {
Self {
timeout,
interval,
start: Instant::now(),
cur_tries: 0,
}
}
}
impl Default for ElementPollerWithTimeout {
fn default() -> Self {
Self::new(Duration::from_secs(20), Duration::from_millis(500))
}
}
#[async_trait::async_trait]
impl ElementPoller for ElementPollerWithTimeout {
async fn tick(&mut self) -> bool {
self.cur_tries += 1;
if self.start.elapsed() >= self.timeout {
return false;
}
let minimum_elapsed = self.interval * self.cur_tries;
let actual_elapsed = self.start.elapsed();
if actual_elapsed < minimum_elapsed {
sleep(minimum_elapsed - actual_elapsed).await;
}
true
}
}
impl IntoElementPoller for ElementPollerWithTimeout {
fn start(&self) -> Box<dyn ElementPoller + Send + Sync> {
Box::new(Self::new(self.timeout, self.interval))
}
}
#[derive(Debug)]
pub struct ElementPollerNoWait;
#[async_trait::async_trait]
impl ElementPoller for ElementPollerNoWait {
async fn tick(&mut self) -> bool {
false
}
}
impl IntoElementPoller for ElementPollerNoWait {
fn start(&self) -> Box<dyn ElementPoller + Send + Sync> {
Box::new(Self)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
async fn test_poller_with_timeout() {
let mut poller =
ElementPollerWithTimeout::new(Duration::from_secs(1), Duration::from_millis(500));
assert!(poller.tick().await);
sleep(Duration::from_millis(500)).await;
assert!(!poller.tick().await);
}
#[tokio::test]
async fn test_poller_nowait() {
let mut poller = ElementPollerNoWait;
assert!(!poller.tick().await); }
}