pub mod action; mod document; mod message; mod mtterror; pub mod name; mod queue; pub use action::*; use document::{Clock, CreateDoc, Session}; use message::{wrapper::Message, MessageAction}; use queue::{ data_director::{Include, Path, RegMsg, Register}, router::Queue, }; use std::sync::mpsc::{channel, Receiver}; use uuid::Uuid; pub use mtterror::{ErrorID, MTTError}; pub use name::{Name, NameType}; #[cfg(test)] mod support_tests { use std::time::Duration; pub static TIMEOUT: Duration = Duration::from_millis(500); } #[derive(Clone)] pub struct MoreThanText { queue: Queue, } impl MoreThanText { pub fn new() -> Self { let queue = Queue::new(); Clock::start(queue.clone()); CreateDoc::start(queue.clone()); Session::start(queue.clone()); Self { queue: queue } } fn new_session() -> UserAction { Addition::new(Session::doc_names()[0].clone()).into() } fn recursive_message_request(&mut self, action: UA) -> Uuid where UA: Into, { match self.records(action) { Ok(data) => { if data.len() == 0 { self.recursive_message_request(MoreThanText::new_session()) } else { let rec = data.iter().last().unwrap(); match rec.get(Name::english("id")).unwrap() { Field::Uuid(id) => id, _ => unreachable!("should always return uuid"), } } } Err(_) => self.recursive_message_request(MoreThanText::new_session()), } } pub fn validate_session(&mut self, session: Option) -> Uuid { let action = match session { Some(data) => match Uuid::try_from(data.as_str()) { Ok(id) => { let mut query = Query::new(Session::doc_names()[0].clone()); let mut calc = Calculation::new(Operand::Equal); calc.add_value(CalcValue::Existing(FieldType::Uuid)) .unwrap(); calc.add_value(id).unwrap(); query.add(Name::english("id"), calc); query.into() } Err(_) => MoreThanText::new_session(), }, None => MoreThanText::new_session(), }; self.recursive_message_request(action) } pub fn records(&mut self, request: UA) -> Result where UA: Into, { let req = request.into(); let (tx, rx) = channel(); let sender_id = self.queue.add_sender(tx); let doc_id = req.doc_name().clone(); let msg = Message::new(req); let msg_id = msg.get_message_id(); let paths = [ Path::new( Include::Just(msg_id.clone()), Include::Just(doc_id.clone()), Include::Just(Action::Records), ), Path::new( Include::Just(msg_id.clone()), Include::Just(doc_id.clone()), Include::Just(Action::Error), ), ]; for path in paths.iter() { let reg_msg = Register::new(sender_id.clone(), RegMsg::AddRoute(path.clone())); self.queue.send(Message::new(reg_msg)); rx.recv().unwrap(); // Wait for completion. } self.queue.send(msg); let result = rx.recv().unwrap(); self.queue.remove_sender(&sender_id); match result.get_action() { MsgAction::Records(data) => Ok(data.clone()), MsgAction::Error(err) => Err(err.clone()), _ => unreachable!("should only receive records or errors"), } } pub fn get_document(&self, name: &str, id: &str) -> Result { if name == "page" { Ok("something".to_string()) } else { Err(MTTError::new(NameType::None, ErrorID::DocumentNotFound)) } } } pub struct TestMoreThanText { mtt: MoreThanText, queue: Queue, } impl TestMoreThanText { pub fn new() -> Self { let mut mtt = MoreThanText::new(); let queue = mtt.queue.clone(); Self { mtt: mtt, queue: queue, } } pub fn validate_session(&mut self, session: Option) -> Uuid { self.mtt.validate_session(session) } pub fn records(&mut self, request: UA) -> Result where UA: Into, { self.mtt.records(request) } pub fn send_time_pulse(&self) { let msg = Clock::gen_message(); self.queue.send(msg); } }