use std::time::Duration;
use std::{collections::HashMap, hash::Hash, ops::DerefMut};
use crate::{kind::MetricKindMask, Generation, MetricKind, Registry};
use parking_lot::Mutex;
use quanta::{Clock, Instant};
#[derive(Debug)]
pub struct Recency<K> {
mask: MetricKindMask,
inner: Mutex<(Clock, HashMap<K, (Generation, Instant)>)>,
idle_timeout: Option<Duration>,
}
impl<K> Recency<K> {
pub fn new(clock: Clock, mask: MetricKindMask, idle_timeout: Option<Duration>) -> Recency<K> {
Recency {
mask,
inner: Mutex::new((clock, HashMap::new())),
idle_timeout,
}
}
pub fn should_store<H>(
&self,
kind: MetricKind,
key: &K,
gen: Generation,
registry: &Registry<K, H>,
) -> bool
where
K: Eq + Hash + Clone + 'static,
H: Clone + 'static,
{
if let Some(idle_timeout) = self.idle_timeout {
if self.mask.matches(kind) {
let mut guard = self.inner.lock();
let (clock, entries) = guard.deref_mut();
let now = clock.now();
if let Some((last_gen, last_update)) = entries.get_mut(&key) {
if *last_gen == gen {
if (now - *last_update) > idle_timeout {
if registry.delete(&key, gen) {
return false;
}
}
} else {
*last_update = now;
}
} else {
entries.insert(key.clone(), (gen, now));
}
}
}
true
}
}