use crate::{ action::{Action, MsgAction, Records}, message::Message, name::{Name, Names}, queue::{ data_director::{Include, Path, RegMsg, Register}, router::Queue, }, }; use std::{ sync::mpsc::channel, thread::{sleep, spawn}, time::Duration, }; pub struct Clock { queue: Queue, } impl Clock { fn new(queue: Queue) -> Self { Self { queue: queue } } pub fn doc_names() -> Vec { vec![Name::english("clock")] } pub fn gen_message() -> Message { Message::new(MsgAction::OnUpdate(Records::new( Clock::doc_names(), Names::new(), ))) } pub fn get_path() -> Path { Path::new( Include::All, Include::Just(Clock::doc_names()[0].clone().into()), Include::Just(Action::OnUpdate), ) } pub fn start(mut queue: Queue) { let clock = Clock::new(queue.clone()); let (tx, rx) = channel(); let id = queue.add_sender(tx); let reg_msg = Register::new(id, RegMsg::AddDocName(Clock::doc_names())); let msg = Message::new(reg_msg.clone()); queue.send(msg); rx.recv().unwrap(); spawn(move || { clock.listen(); }); } fn listen(&self) { loop { self.queue.send(Clock::gen_message()); sleep(Duration::from_secs(1)); } } } #[cfg(test)] mod clocks { use super::*; use crate::queue::{ data_director::{Include, Path}, router::TestClock, }; use chrono::{TimeDelta, Utc}; static TIMEOUT: Duration = Duration::from_millis(1500); #[test] fn does_clock_send_reply_every_second() { let clock = TestClock::new(); let mut queue = Queue::with_clock(clock); let (tx, rx) = channel(); let id = queue.add_sender(tx); let request = Register::new( id.clone(), RegMsg::AddRoute(Path::new(Include::All, Include::All, Include::All)), ); queue.send(Message::new(request)); rx.recv_timeout(TIMEOUT).unwrap(); let mut holder: Vec = Vec::new(); let start = Utc::now(); Clock::start(queue.clone()); while holder.len() < 2 { holder.push(rx.recv_timeout(TIMEOUT).unwrap()); } let end = Utc::now(); assert!((end - start) > TimeDelta::seconds(1)); assert!((end - start) < TimeDelta::seconds(2)); let reg_request = Register::new(id, RegMsg::GetNameID(Clock::doc_names()[0].clone())); queue.send(Message::new(reg_request)); rx.recv_timeout(TIMEOUT).unwrap(); for msg in holder.iter() { let action = msg.get_action(); match action { MsgAction::OnUpdate(result) => assert_eq!(result.len(), 0), _ => unreachable!("got {:?}, should have been empty record", action), } } } }