use std::sync::Arc;
use std::time::Duration;
use crate::ctx::Ctx;
use crate::error::Result;
use crate::monitor::handler::Handler;
use crate::protocol::event_typed::Tick;
type BoxedTickHandler = Arc<dyn Fn(&Tick, &mut Ctx<'_>) -> Result<()> + Send + Sync>;
pub struct TickRegistration {
pub period: Duration,
#[allow(dead_code)]
pub(crate) handler: BoxedTickHandler,
}
impl TickRegistration {
pub fn new<H, M>(period: Duration, handler: H) -> Self
where
H: Handler<Tick, M>,
M: 'static,
{
Self {
period,
handler: Arc::new(move |tick, ctx| handler.call(tick, ctx)),
}
}
}
impl std::fmt::Debug for TickRegistration {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("TickRegistration")
.field("period", &self.period)
.finish_non_exhaustive()
}
}
#[cfg(test)]
mod tests {
use std::sync::Arc;
use std::sync::atomic::{AtomicU32, Ordering};
use flowscope::Timestamp;
use super::*;
use crate::anomaly::sink::NoopSink;
use crate::ctx::{CounterRegistry, SourceIdx, StateMap};
#[test]
fn tick_registration_invokes_handler() {
let counter = Arc::new(AtomicU32::new(0));
let c = Arc::clone(&counter);
let reg = TickRegistration::new(Duration::from_millis(100), move |_t: &Tick| {
c.fetch_add(1, Ordering::Relaxed);
Ok(())
});
let mut state = StateMap::default();
let mut sink = NoopSink;
let mut counters = CounterRegistry::default();
let mut flow_states = crate::ctx::FlowStateRegistry::default();
let mut ctx = Ctx {
flow: None,
ts: Timestamp::new(0, 0),
source: SourceIdx(0),
monitor_name: None,
state_map: &mut state,
sink: &mut sink,
counters: &mut counters,
flow_states: &mut flow_states,
label_table: crate::ctx::default_label_table(),
tracker: None,
};
let tick = Tick {
now: Timestamp::new(0, 0),
period: Duration::from_millis(100),
};
(reg.handler)(&tick, &mut ctx).unwrap();
assert_eq!(counter.load(Ordering::Relaxed), 1);
assert_eq!(reg.period, Duration::from_millis(100));
}
}