#![allow(dead_code)]
#[derive(Debug, Clone)]
#[allow(dead_code)]
pub struct ThrottleConfig {
pub interval_ms: u64,
}
#[derive(Debug, Clone)]
#[allow(dead_code)]
pub struct EventThrottle {
config: ThrottleConfig,
last_pass_tick: u64,
current_tick: u64,
pass_count: u64,
drop_count: u64,
active: bool,
first_event: bool,
}
#[allow(dead_code)]
pub fn default_throttle_config() -> ThrottleConfig {
ThrottleConfig { interval_ms: 100 }
}
#[allow(dead_code)]
pub fn new_event_throttle(config: ThrottleConfig) -> EventThrottle {
EventThrottle {
config,
last_pass_tick: 0,
current_tick: 0,
pass_count: 0,
drop_count: 0,
active: true,
first_event: true,
}
}
#[allow(dead_code)]
pub fn advance_throttle_tick(et: &mut EventThrottle, delta_ms: u64) {
et.current_tick += delta_ms;
}
#[allow(dead_code)]
pub fn throttle_event(et: &mut EventThrottle) -> bool {
if !et.active {
return false;
}
if et.first_event {
et.first_event = false;
et.last_pass_tick = et.current_tick;
et.pass_count += 1;
return true;
}
let elapsed = et.current_tick.saturating_sub(et.last_pass_tick);
if elapsed >= et.config.interval_ms {
et.last_pass_tick = et.current_tick;
et.pass_count += 1;
true
} else {
et.drop_count += 1;
false
}
}
#[allow(dead_code)]
pub fn throttle_count(et: &EventThrottle) -> u64 {
et.pass_count
}
#[allow(dead_code)]
pub fn reset_throttle(et: &mut EventThrottle) {
et.last_pass_tick = et.current_tick;
et.pass_count = 0;
et.drop_count = 0;
et.first_event = true;
}
#[allow(dead_code)]
pub fn throttle_interval_ms(et: &EventThrottle) -> u64 {
et.config.interval_ms
}
#[allow(dead_code)]
pub fn events_dropped(et: &EventThrottle) -> u64 {
et.drop_count
}
#[allow(dead_code)]
pub fn throttle_is_active(et: &EventThrottle) -> bool {
et.active
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_new_event_throttle() {
let et = new_event_throttle(default_throttle_config());
assert_eq!(throttle_count(&et), 0);
assert!(throttle_is_active(&et));
}
#[test]
fn test_first_event_passes() {
let mut et = new_event_throttle(ThrottleConfig { interval_ms: 100 });
assert!(throttle_event(&mut et));
}
#[test]
fn test_second_event_too_fast() {
let mut et = new_event_throttle(ThrottleConfig { interval_ms: 100 });
throttle_event(&mut et);
assert!(!throttle_event(&mut et));
}
#[test]
fn test_event_passes_after_interval() {
let mut et = new_event_throttle(ThrottleConfig { interval_ms: 100 });
throttle_event(&mut et);
advance_throttle_tick(&mut et, 100);
assert!(throttle_event(&mut et));
}
#[test]
fn test_events_dropped_count() {
let mut et = new_event_throttle(ThrottleConfig { interval_ms: 100 });
throttle_event(&mut et);
throttle_event(&mut et);
throttle_event(&mut et);
assert_eq!(events_dropped(&et), 2);
}
#[test]
fn test_reset_throttle() {
let mut et = new_event_throttle(ThrottleConfig { interval_ms: 100 });
throttle_event(&mut et);
reset_throttle(&mut et);
assert_eq!(throttle_count(&et), 0);
assert_eq!(events_dropped(&et), 0);
}
#[test]
fn test_throttle_interval_ms() {
let et = new_event_throttle(ThrottleConfig { interval_ms: 250 });
assert_eq!(throttle_interval_ms(&et), 250);
}
#[test]
fn test_inactive_throttle_drops_all() {
let mut et = new_event_throttle(ThrottleConfig { interval_ms: 0 });
et.active = false;
assert!(!throttle_event(&mut et));
}
}