use std::time::{Duration, Instant};
use reqwest::Client;
use tokio_util::sync::CancellationToken;
use crate::engine::metrics::statistics;
const SAMPLE_INTERVAL: Duration = Duration::from_millis(400);
const SAMPLE_TIMEOUT: Duration = Duration::from_secs(4);
const MIN_SAMPLES: usize = 3;
pub async fn sample_until_stopped(
client: &Client,
url: &str,
stop: &CancellationToken,
) -> Option<f64> {
let mut samples = Vec::new();
let mut sequence: u32 = 0;
loop {
sequence = sequence.wrapping_add(1);
let separator = if url.contains('?') { '&' } else { '?' };
let request = client
.get(format!("{url}{separator}bloat={sequence}"))
.header(reqwest::header::CACHE_CONTROL, "no-cache")
.send();
let started = Instant::now();
tokio::select! {
() = stop.cancelled() => break,
outcome = tokio::time::timeout(SAMPLE_TIMEOUT, request) => {
if let Ok(Ok(response)) = outcome {
if response.status().is_success() {
samples.push(started.elapsed().as_secs_f64() * 1000.0);
}
}
}
}
tokio::select! {
() = stop.cancelled() => break,
() = tokio::time::sleep(SAMPLE_INTERVAL) => {}
}
}
if samples.len() < MIN_SAMPLES {
return None;
}
statistics::median(&samples)
}