use {
crate::{Mode, MINIMUM_SIGNATURE_INTERVAL_NANOS},
fuchsia_triage::SnapshotTrigger,
injectable_time::TimeSource,
std::collections::HashMap,
std::sync::Arc,
tracing::warn,
};
pub struct DelayTracker {
last_sent: HashMap<String, i64>,
time_source: Arc<dyn TimeSource + Send + Sync>,
program_mode: Mode,
}
impl DelayTracker {
pub(crate) fn new(
time_source: Arc<dyn TimeSource + Send + Sync>,
program_mode: Mode,
) -> DelayTracker {
DelayTracker { last_sent: HashMap::new(), time_source, program_mode }
}
fn appropriate_report_interval(&self, desired_interval: i64) -> i64 {
if self.program_mode == Mode::IntegrationTest
|| desired_interval >= MINIMUM_SIGNATURE_INTERVAL_NANOS
{
desired_interval
} else {
MINIMUM_SIGNATURE_INTERVAL_NANOS
}
}
pub(crate) fn ok_to_send(&mut self, snapshot: &SnapshotTrigger) -> bool {
let now = self.time_source.now();
let interval = self.appropriate_report_interval(snapshot.interval);
let should_send = match self.last_sent.get(&snapshot.signature) {
None => true,
Some(time) => time <= &(now - interval),
};
if should_send {
self.last_sent.insert(snapshot.signature.to_string(), now);
if snapshot.interval < MINIMUM_SIGNATURE_INTERVAL_NANOS {
warn!(
"Signature {} has interval {} nanos, less than minimum {}",
snapshot.signature, snapshot.interval, MINIMUM_SIGNATURE_INTERVAL_NANOS
);
}
}
should_send
}
}
#[cfg(test)]
mod test {
use super::*;
use injectable_time::FakeTime;
use static_assertions::const_assert;
#[fuchsia::test]
fn verify_test_mode() {
let time = Arc::new(FakeTime::new());
let mut tracker = DelayTracker::new(time.clone(), Mode::IntegrationTest);
time.set_ticks(1);
let trigger_slow = SnapshotTrigger { signature: "slow".to_string(), interval: 10 };
let trigger_fast = SnapshotTrigger { signature: "fast".to_string(), interval: 1 };
let ok_slow_1 = tracker.ok_to_send(&trigger_slow);
let ok_fast_1 = tracker.ok_to_send(&trigger_fast);
time.set_ticks(3);
let ok_slow_2 = tracker.ok_to_send(&trigger_slow);
let ok_fast_2 = tracker.ok_to_send(&trigger_fast);
assert!(ok_slow_1);
assert!(ok_fast_1);
assert!(!ok_slow_2);
assert!(ok_fast_2);
}
#[fuchsia::test]
fn verify_appropriate_report_interval() {
const_assert!(MINIMUM_SIGNATURE_INTERVAL_NANOS > 1);
let time = Arc::new(FakeTime::new());
let test_tracker = DelayTracker::new(time.clone(), Mode::IntegrationTest);
let production_tracker = DelayTracker::new(time, Mode::Production);
assert_eq!(test_tracker.appropriate_report_interval(1), 1);
assert_eq!(
production_tracker.appropriate_report_interval(1),
MINIMUM_SIGNATURE_INTERVAL_NANOS
);
}
}