Added names structure to establish routes.
Some checks failed
Gitea Actions Demo / Explore-Gitea-Actions (push) Failing after 1s

This commit is contained in:
Jeff Baskin 2025-09-28 17:15:18 -04:00
parent 7ba0740ce5
commit 3490116775

View File

@ -27,6 +27,10 @@ enum MTTError {
DocumentFieldWrongDataType(FieldType, FieldType),
DocumentNotFound(String),
FieldDuplicate(String, Field),
NameDuplicate(Name),
NameInvalidID(Uuid),
NameMissingTranslation(Language),
NameNotFound(Name),
QueryCannotChangeData,
}
@ -77,7 +81,7 @@ impl NameID {
fn is_none(&self) -> bool {
match self {
Self::None => true,
_ => false
_ => false,
}
}
}
@ -397,7 +401,7 @@ mod messages {
}
}
#[derive(Clone, Debug)]
#[derive(Clone, Debug, Eq, Hash)]
enum Include<T> {
All,
Some(T),
@ -458,19 +462,30 @@ impl From<Route> for RouteID {
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
struct Name {
name: String,
lang: Language,
}
impl Name {
fn get_language(&self) -> &Language {
&self.lang
}
fn english(name: String) -> Self {
Self {
name: name,
lang: Language::from_639_1("en").unwrap(),
}
}
fn japanese(name: String) -> Self {
Self {
name: name,
lang: Language::from_639_1("ja").unwrap(),
}
}
}
impl ToString for Name {
@ -479,8 +494,226 @@ impl ToString for Name {
}
}
#[derive(Debug)]
struct Names {
names: HashMap<Name, Uuid>,
ids: HashMap<Uuid, HashMap<Language, Name>>,
}
impl Names {
fn new() -> Self {
Self {
names: HashMap::new(),
ids: HashMap::new(),
}
}
fn add_name(&mut self, name: Name) -> Result<Uuid, MTTError> {
if self.names.contains_key(&name) {
return Err(MTTError::NameDuplicate(name));
}
let mut id = Uuid::new_v4();
while self.ids.contains_key(&id) {
id = Uuid::new_v4();
}
self.names.insert(name.clone(), id.clone());
let mut holder: HashMap<Language, Name> = HashMap::new();
holder.insert(name.get_language().clone(), name);
self.ids.insert(id.clone(), holder);
Ok(id)
}
fn add_translation(&mut self, name: Name, translation: Name) -> Result<Uuid, MTTError> {
let id = match self.get_id(&name) {
Ok(data) => data.clone(),
Err(err) => return Err(err),
};
match self.get_id(&translation) {
Ok(_) => return Err(MTTError::NameDuplicate(translation)),
Err(_) => {}
}
let holder = self.ids.get_mut(&id).unwrap();
holder.insert(translation.get_language().clone(), translation.clone());
self.names.insert(translation, id);
Ok(id.clone())
}
fn get_name(&self, id: &Uuid, lang: &Language) -> Result<Name, MTTError> {
match self.ids.get(id) {
Some(langdb) => match langdb.get(lang) {
Some(name) => Ok(name.clone()),
None => Err(MTTError::NameMissingTranslation(lang.clone())),
},
None => Err(MTTError::NameInvalidID(id.clone())),
}
}
fn get_id(&self, name: &Name) -> Result<&Uuid, MTTError> {
match self.names.get(name) {
Some(id) => Ok(id),
None => Err(MTTError::NameNotFound(name.clone())),
}
}
}
#[cfg(test)]
mod names {
use super::*;
#[test]
fn are_name_ids_unique() {
let mut names = Names::new();
let data = ["one", "two", "three", "four", "five"];
let mut ids: HashSet<Uuid> = HashSet::new();
for item in data.iter() {
let name = Name::english(item.to_string());
ids.insert(names.add_name(name).unwrap());
}
assert_eq!(ids.len(), data.len());
}
#[test]
fn does_id_return_name() {
let mut names = Names::new();
let data = ["one", "two"];
let mut ids: HashMap<Name, Uuid> = HashMap::new();
for item in data.iter() {
let name = Name::english(item.to_string());
ids.insert(name.clone(), names.add_name(name).unwrap());
}
for (name, id) in ids.iter() {
assert_eq!(
&names
.get_name(id, &Language::from_639_1("en").unwrap())
.unwrap(),
name
);
assert_eq!(names.get_id(name).unwrap(), id);
}
}
#[test]
fn errors_on_name_not_found() {
let mut names = Names::new();
let name = Name::english("missing".to_string());
let result = names.get_id(&name);
match result {
Ok(_) => unreachable!("got {:?}, should have been error", result),
Err(err) => match err {
MTTError::NameNotFound(output) => assert_eq!(output, name),
_ => unreachable!("got {:?}, should have been name not found", err),
},
}
}
#[test]
fn errors_on_bad_id() {
let mut names = Names::new();
let id = Uuid::new_v4();
let result = names.get_name(&id, &Language::from_639_1("en").unwrap());
match result {
Ok(_) => unreachable!("got {:?}, should be invalid id error", result),
Err(err) => match err {
MTTError::NameInvalidID(data) => assert_eq!(data, id),
_ => unreachable!("got {:?}, should have been invalid id", err),
},
}
}
#[test]
fn errors_on_missing_translation() {
let mut names = Names::new();
let name = Name::english("task".to_string());
let lang = Language::from_639_1("ja").unwrap();
let id = names.add_name(name).unwrap();
let result = names.get_name(&id, &lang);
match result {
Ok(_) => unreachable!("got {:?}, should be invalid id error", result),
Err(err) => match err {
MTTError::NameMissingTranslation(data) => assert_eq!(data, lang),
_ => unreachable!("got {:?}, should have been invalid id", err),
},
}
}
#[test]
fn errors_on_duplicate_names() {
let mut names = Names::new();
let data = "test".to_string();
let name = Name::english(data.clone());
let id = names.add_name(name.clone());
let output = names.add_name(name.clone());
match output {
Ok(_) => unreachable!(
"got {:?}, should have produced duplicate name error",
output
),
Err(err) => match err {
MTTError::NameDuplicate(result) => assert_eq!(result, name),
_ => unreachable!("got {:?}, should have been duplicate name", err),
},
}
}
#[test]
fn allows_alternate_names() {
let mut names = Names::new();
let data = "test".to_string();
let alt = "テスト".to_string();
let english = Name::english(data.clone());
let japanese = Name::japanese(alt.clone());
let id = names.add_name(english.clone()).unwrap();
let result = names.add_translation(english, japanese.clone()).unwrap();
assert_eq!(result, id);
println!("\n{:?}", names);
let output = names.get_name(&id, &Language::from_639_1("ja").unwrap());
assert_eq!(output.unwrap().to_string(), alt);
assert_eq!(names.get_id(&japanese).unwrap(), &id);
}
#[test]
fn errors_on_bad_translation() {
let mut names = Names::new();
let data = "test".to_string();
let alt = "テスト".to_string();
let english = Name::english(data.clone());
let japanese = Name::japanese(alt.clone());
let result = names.add_translation(japanese.clone(), english);
match result {
Ok(_) => unreachable!("got {:?}, should be invalid id error", result),
Err(err) => match err {
MTTError::NameNotFound(output) => assert_eq!(output, japanese),
_ => unreachable!("got {:?}, should have been invalid id", err),
},
}
}
#[test]
fn errors_on_translation_duplicates() {
let mut names = Names::new();
let data = "test".to_string();
let alt = "テスト".to_string();
let english = Name::english(data.clone());
let japanese = Name::japanese(alt.clone());
let id = names.add_name(english.clone()).unwrap();
let id = names.add_name(japanese.clone()).unwrap();
let result = names.add_translation(english, japanese.clone());
match result {
Ok(_) => unreachable!(
"got {:?}, should have produced duplicate name error",
result
),
Err(err) => match err {
MTTError::NameDuplicate(result) => assert_eq!(result, japanese),
_ => unreachable!("got {:?}, should have been duplicate name", err),
},
}
}
}
#[derive(Clone, Debug)]
enum RegMsg {
AddRoute(RouteRequest),
DocName(Name),
Error(MTTError),
Ok,
@ -499,7 +732,7 @@ impl Register {
sender_id: sender_id,
}
}
fn get_msg(&self) -> &RegMsg {
&self.msg
}
@ -650,7 +883,7 @@ mod routes {
}
}
#[derive(Clone)]
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
struct RouteRequest {
msg_id: Include<Uuid>,
doc_name: Include<String>,
@ -968,6 +1201,7 @@ struct DocRegistry {
doc_names: Vec<Name>,
queue: Queue,
receiver: Receiver<Message>,
routes: HashMap<RouteRequest, Uuid>,
}
impl DocRegistry {
@ -976,6 +1210,7 @@ impl DocRegistry {
doc_names: Vec::new(),
queue: queue,
receiver: rx,
routes: HashMap::new(),
}
}
@ -994,8 +1229,8 @@ impl DocRegistry {
let id = data.get_sender_id();
let reply = msg.response(self.register_action(data));
self.queue.forward(id, reply);
},
_ => {},
}
_ => {}
}
}
}
@ -1004,12 +1239,19 @@ impl DocRegistry {
match reg.get_msg() {
RegMsg::DocName(name) => {
if self.doc_names.contains(name) {
reg.response(RegMsg::Error(MTTError::DocumentAlreadyExists(name.to_string())))
reg.response(RegMsg::Error(MTTError::DocumentAlreadyExists(
name.to_string(),
)))
} else {
self.doc_names.push(name.clone());
reg.response(RegMsg::Ok)
}
},
}
RegMsg::AddRoute(route) => {
self.routes
.insert(route.clone(), reg.get_sender_id().clone());
reg.response(RegMsg::Ok)
}
_ => reg.response(RegMsg::Ok),
}
}
@ -1157,6 +1399,8 @@ mod queues {
sender_id: Uuid,
queue: Queue,
receiver: Receiver<Message>,
doc_id: HashMap<String, Uuid>,
doc_rx: HashMap<String, Receiver<Message>>,
}
impl TestQueue {
@ -1168,9 +1412,22 @@ mod queues {
sender_id: id,
queue: queue,
receiver: rx,
doc_id: HashMap::new(),
doc_rx: HashMap::new(),
}
}
fn add_document(&mut self, name: String) {
let (tx, rx) = channel();
let id = self.add_sender(tx);
let reg_msg = Register::new(id.clone(), RegMsg::DocName(Name::english(name.clone())));
let msg = Message::new(NameID::None, reg_msg);
self.send(msg.clone()).unwrap();
let result = rx.recv_timeout(TIMEOUT).unwrap();
self.doc_id.insert(name.clone(), id);
self.doc_rx.insert(name.clone(), rx);
}
fn get_preset_id(&self) -> &Uuid {
&self.sender_id
}
@ -1179,6 +1436,14 @@ mod queues {
&self.receiver
}
fn get_doc_rx_id(&self, name: &str) -> &Uuid {
self.doc_id.get(name).unwrap()
}
fn get_doc_rx(&self, name: &str) -> &Receiver<Message> {
self.doc_rx.get(name).unwrap()
}
fn add_sender(&mut self, sender: Sender<Message>) -> Uuid {
self.queue.add_sender(sender)
}
@ -1217,7 +1482,10 @@ mod queues {
fn can_register_document_name() {
let mut queue = TestQueue::new();
let doc_name = Name::english(Uuid::new_v4().to_string());
let reg_msg = Register::new(queue.get_preset_id().clone(), RegMsg::DocName(doc_name.clone()));
let reg_msg = Register::new(
queue.get_preset_id().clone(),
RegMsg::DocName(doc_name.clone()),
);
let msg = Message::new(NameID::None, reg_msg);
queue.send(msg.clone()).unwrap();
let result = queue.get_preset_rx().recv_timeout(TIMEOUT).unwrap();
@ -1225,7 +1493,7 @@ mod queues {
let action = result.get_action();
match action {
MsgAction::Register(data) => match data.get_msg() {
RegMsg::Ok => {},
RegMsg::Ok => {}
_ => unreachable!("got {:?}, should have been register ok", action),
},
_ => unreachable!("got {:?}, should have been register ok", action),
@ -1235,12 +1503,12 @@ mod queues {
#[test]
fn errors_on_duplicate_names() {
let mut queue = TestQueue::new();
//let mut queue = Queue::new();
//let (sender, receiver) = channel();
//let id = queue.add_sender(sender);
let receiver = queue.get_preset_rx();
let doc_name = Name::english(Uuid::new_v4().to_string());
let reg_msg = Register::new(queue.get_preset_id().clone(), RegMsg::DocName(doc_name.clone()));
let reg_msg = Register::new(
queue.get_preset_id().clone(),
RegMsg::DocName(doc_name.clone()),
);
let msg = Message::new(NameID::None, reg_msg.clone());
queue.send(msg.clone()).unwrap();
receiver.recv_timeout(TIMEOUT).unwrap();
@ -1252,7 +1520,9 @@ mod queues {
match action {
MsgAction::Register(data) => match data.get_msg() {
RegMsg::Error(err) => match err {
MTTError::DocumentAlreadyExists(name) => assert_eq!(name.to_string(), doc_name.to_string()),
MTTError::DocumentAlreadyExists(name) => {
assert_eq!(name.to_string(), doc_name.to_string())
}
_ => unreachable!("got {:?}, should have been duplicate error", err),
},
_ => unreachable!("got {:?}, should have been error", data),
@ -1261,20 +1531,25 @@ mod queues {
}
}
#[test]
fn can_register_routes() {
}
#[test]
#[ignore]
fn default_send_does_nothing() {
let mut queue = Queue::new();
let (sender, receiver) = channel();
let id = queue.add_sender(sender);
let msg = Message::new("wiki", Query::new());
fn can_register_routes() {
let mut queue = TestQueue::new();
let names = ["task", "recipe"];
for name in names.iter() {
queue.add_document(name.to_string());
}
let route_req = RouteRequest::new(Include::All, Include::All, Include::All);
let reg_msg = RegMsg::AddRoute(route_req);
let reg = Register::new(queue.get_doc_rx_id(names[0]).clone(), reg_msg);
let msg = Message::new(NameID::None, reg);
queue.send(msg).unwrap();
match receiver.recv_timeout(TIMEOUT) {
queue.get_doc_rx(names[0]).recv_timeout(TIMEOUT).unwrap();
let msg = Message::new(NameID::None, Query::new());
queue.send(msg.clone()).unwrap();
let result = queue.get_doc_rx(names[0]).recv_timeout(TIMEOUT).unwrap();
assert_eq!(result.get_message_id(), msg.get_message_id());
match queue.get_doc_rx(names[1]).recv_timeout(TIMEOUT) {
Ok(msg) => unreachable!("should not receive: {:?}", msg),
Err(err) => match err {
RecvTimeoutError::Timeout => {}