use nodedb_types::timeseries::PartitionInterval;
#[derive(Debug, Clone)]
pub struct RateEstimator {
rate: f64,
alpha: f64,
last_update_ms: i64,
rows_since_update: u64,
}
impl RateEstimator {
pub fn new() -> Self {
Self {
rate: 0.0,
alpha: 0.1,
last_update_ms: 0,
rows_since_update: 0,
}
}
pub fn record(&mut self, n: u64, now_ms: i64) {
if self.last_update_ms == 0 {
self.last_update_ms = now_ms;
self.rows_since_update = n;
return;
}
self.rows_since_update += n;
let elapsed_ms = now_ms - self.last_update_ms;
if elapsed_ms >= 1000 {
let elapsed_s = elapsed_ms as f64 / 1000.0;
let instant_rate = self.rows_since_update as f64 / elapsed_s;
self.rate = self.alpha * instant_rate + (1.0 - self.alpha) * self.rate;
self.last_update_ms = now_ms;
self.rows_since_update = 0;
}
}
pub fn rate(&self) -> f64 {
self.rate
}
pub fn suggest_interval(&self) -> PartitionInterval {
let r = self.rate;
if r > 100_000.0 {
PartitionInterval::Duration(3_600_000) } else if r > 1_000.0 {
PartitionInterval::Duration(86_400_000) } else if r > 10.0 {
PartitionInterval::Duration(604_800_000) } else if r > 0.1 {
PartitionInterval::Month
} else {
PartitionInterval::Unbounded
}
}
}
impl Default for RateEstimator {
fn default() -> Self {
Self::new()
}
}