Added error when field name not in document definition.

This commit is contained in:
Jeff Baskin 2025-08-10 11:14:32 -04:00
parent 92f1814d1c
commit 7dbbe2fdce

View File

@ -215,6 +215,14 @@ impl Message {
&self.action &self.action
} }
fn response<A>(&self, action: A) -> Self where A: Into<MsgAction> {
Self {
msg_id: self.msg_id.clone(),
document_id: self.document_id.clone(),
action: action.into(),
}
}
fn reply(&self, resp: Reply) -> Self { fn reply(&self, resp: Reply) -> Self {
Self { Self {
msg_id: self.msg_id.clone(), msg_id: self.msg_id.clone(),
@ -330,6 +338,32 @@ mod messages {
_ => unreachable!("should have been a reply"), _ => unreachable!("should have been a reply"),
} }
} }
#[test]
fn can_make_a_response_message() {
let doc_id = Uuid::new_v4();
let msg = Message::new(doc_id.clone(), MsgAction::Query(Query::new()));
let data = Uuid::new_v4().to_string();
let result1 = msg.response(MTTError::DocumentNotFound(data.clone()));
let result2 = msg.response(Reply::new());
assert_eq!(result1.get_message_id(), msg.get_message_id());
assert_eq!(result2.get_message_id(), msg.get_message_id());
assert_eq!(result1.get_document_id(), msg.get_document_id());
assert_eq!(result2.get_document_id(), msg.get_document_id());
let action1 = result1.get_action();
match action1 {
MsgAction::Error(err) => match err {
MTTError::DocumentNotFound(output) => assert_eq!(output, &data),
_ => unreachable!("got {:?}: should have received document not found", err),
},
_ => unreachable!("got {:?}: should have received error", action1),
}
let action2 = result2.get_action();
match action2 {
MsgAction::Reply(data) => assert_eq!(data.len(), 0),
_ => unreachable!("got {:?}: should have received a reply", action2),
}
}
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
@ -1243,6 +1277,8 @@ mod replies {
} }
} }
type DocumentMap = HashMap<String, Field>;
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
struct Document { struct Document {
data: HashMap<String, Field>, data: HashMap<String, Field>,
@ -1267,6 +1303,15 @@ impl Document {
} }
} }
impl<'a> IntoIterator for &'a Document {
type Item = <&'a DocumentMap as IntoIterator>::Item;
type IntoIter = <&'a DocumentMap as IntoIterator>::IntoIter;
fn into_iter(self) -> Self::IntoIter {
(&self.data).into_iter()
}
}
#[cfg(test)] #[cfg(test)]
mod documents { mod documents {
use super::*; use super::*;
@ -1298,14 +1343,16 @@ mod documents {
} }
struct DocumentFile { struct DocumentFile {
docdef: DocDef,
docs: Vec<Document>, docs: Vec<Document>,
queue: Queue, queue: Queue,
rx: Receiver<Message>, rx: Receiver<Message>,
} }
impl DocumentFile { impl DocumentFile {
fn new(queue: Queue, rx: Receiver<Message>) -> Self { fn new(queue: Queue, rx: Receiver<Message>, docdef: DocDef) -> Self {
Self { Self {
docdef: docdef,
docs: Vec::new(), docs: Vec::new(),
queue: queue, queue: queue,
rx: rx, rx: rx,
@ -1344,7 +1391,12 @@ impl DocumentFile {
return; return;
} }
} }
let mut doc = DocumentFile::new(queue.clone(), rx); let action = msg.get_action();
let docdef = match action {
MsgAction::Create(data) => data.clone(),
_ => unreachable!("got {:?}: should have been a create message", action),
};
let mut doc = DocumentFile::new(queue.clone(), rx, docdef);
spawn(move || { spawn(move || {
doc.listen(); doc.listen();
}); });
@ -1355,29 +1407,35 @@ impl DocumentFile {
fn listen(&mut self) { fn listen(&mut self) {
loop { loop {
let msg = self.rx.recv().unwrap(); let msg = self.rx.recv().unwrap();
let reply = match msg.get_action() { let result = match msg.get_action() {
MsgAction::Addition(data) => self.add_document(data), MsgAction::Addition(data) => self.add_document(data),
MsgAction::Query(query) => self.query(query), MsgAction::Query(query) => self.query(query),
_ => Reply::new(), _ => Reply::new().into(),
}; };
self.queue.send(msg.reply(reply)).unwrap(); self.queue.send(msg.response(result)).unwrap();
} }
} }
fn add_document(&mut self, addition: &Addition) -> Reply { fn add_document(&mut self, addition: &Addition) -> MsgAction {
let mut reply = Reply::new(); let mut reply = Reply::new();
let doc = addition.get_document(); let doc = addition.get_document();
for (key, value) in doc.into_iter() {
match self.docdef.get_field(&key) {
Err(err) => return err.into(),
Ok(_) => {},
}
}
self.docs.push(doc.clone()); self.docs.push(doc.clone());
reply.add(doc); reply.add(doc);
reply reply.into()
} }
fn query(&self, query: &Query) -> Reply { fn query(&self, query: &Query) -> MsgAction {
let mut reply = Reply::new(); let mut reply = Reply::new();
for doc in self.docs.iter() { for doc in self.docs.iter() {
reply.add(doc.clone()); reply.add(doc.clone());
} }
reply reply.into()
} }
} }
@ -1394,6 +1452,14 @@ mod document_files {
.to_vec() .to_vec()
} }
fn create_docdef(num: usize) -> DocDef {
let mut output = DocDef::new();
for count in 0..num {
output.add_field(format!("field{}", count), FieldType::Uuid);
}
output
}
fn test_doc( fn test_doc(
name: &str, name: &str,
docdef: DocDef, docdef: DocDef,
@ -1590,6 +1656,25 @@ mod document_files {
_ => unreachable!("got {:?}: should have been a reply", result.get_action()), _ => unreachable!("got {:?}: should have been a reply", result.get_action()),
} }
} }
#[test]
fn errors_on_wrong_field_name() {
let doc_name = "mismatch";
let field_name = Uuid::new_v4().to_string();
let (queue, rx) = test_doc(doc_name, create_docdef(1), standard_routes());
let mut addition = Addition::new();
addition.add_field(field_name.clone(), Uuid::new_v4());
let msg = Message::new(doc_name, addition);
queue.send(msg).unwrap();
let result = rx.recv_timeout(TIMEOUT).unwrap();
match result.get_action() {
MsgAction::Error(err) => match err {
MTTError::DocumentFieldNotFound(data) => assert_eq!(data, &field_name),
_ => unreachable!("got {:?}: should have been document field not found.", err),
}
_ => unreachable!("got {:?}: should have been an error", result.get_action()),
}
}
} }
#[cfg(test)] #[cfg(test)]