morethantext/src/message.rs

751 lines
21 KiB
Rust
Raw Normal View History

2025-07-17 09:12:23 -04:00
use std::{
collections::HashMap,
sync::{
mpsc::{channel, Receiver, Sender},
Arc, RwLock,
},
2025-07-25 11:08:47 -04:00
thread::spawn,
2025-07-17 09:12:23 -04:00
};
use uuid::Uuid;
#[derive(Clone, Debug)]
enum MTTError {
DocumentAlreadyExists(String),
DocumentNotFound(String),
2025-07-17 09:12:23 -04:00
RouteNoListeners,
}
2025-07-17 09:12:23 -04:00
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
enum Action {
2025-07-25 11:08:47 -04:00
Create,
2025-07-28 10:49:34 -04:00
Query,
2025-07-25 11:08:47 -04:00
//
2025-07-17 09:12:23 -04:00
NewDocumentType,
Reply,
Update,
}
2025-07-28 10:49:34 -04:00
impl From<MsgAction> for Action {
fn from(value: MsgAction) -> Self {
match value {
MsgAction::Create(_) => Action::Create,
MsgAction::Query(_) => Action::Query,
}
}
}
impl From<&MsgAction> for Action {
fn from(value: &MsgAction) -> Self {
let action = value.clone();
Self::from(action)
}
}
2025-07-25 11:08:47 -04:00
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2025-07-17 09:12:23 -04:00
enum NameID {
ID(Uuid),
Name(String),
}
2025-07-17 09:12:23 -04:00
impl From<&str> for NameID {
fn from(value: &str) -> Self {
Self::Name(value.to_string())
}
}
2025-07-17 09:12:23 -04:00
impl From<String> for NameID {
fn from(value: String) -> Self {
Self::Name(value)
}
}
2025-07-17 09:12:23 -04:00
impl From<Uuid> for NameID {
fn from(value: Uuid) -> Self {
Self::ID(value)
}
}
2025-07-20 10:39:15 -04:00
impl From<&NameID> for NameID {
fn from(value: &NameID) -> Self {
value.clone()
}
}
2025-07-28 10:49:34 -04:00
#[derive(Clone)]
enum MsgAction {
Create(DocDef),
Query(Access),
}
#[derive(Clone)]
struct Message {
msg_id: Uuid,
2025-07-17 09:12:23 -04:00
document_id: NameID,
2025-07-28 10:49:34 -04:00
action: MsgAction,
}
impl Message {
2025-07-28 10:49:34 -04:00
fn new<D>(doc_id: D, action: MsgAction) -> Self
2025-07-17 09:12:23 -04:00
where
D: Into<NameID>,
{
Self {
msg_id: Uuid::new_v4(),
document_id: doc_id.into(),
2025-07-17 09:12:23 -04:00
action: action,
}
}
fn get_message_id(&self) -> &Uuid {
&self.msg_id
}
2025-07-17 09:12:23 -04:00
fn get_document_id(&self) -> &NameID {
&self.document_id
}
2025-07-28 10:49:34 -04:00
fn get_action(&self) -> &MsgAction {
2025-07-17 09:12:23 -04:00
&self.action
}
}
#[cfg(test)]
mod messages {
use super::*;
#[test]
fn can_the_document_be_a_stringi_reference() {
let dts = ["one", "two"];
for document in dts.into_iter() {
2025-07-28 10:49:34 -04:00
let msg = Message::new(document, MsgAction::Create(DocDef::new()));
match msg.get_document_id() {
2025-07-17 09:12:23 -04:00
NameID::ID(_) => unreachable!("should have been a string id"),
NameID::Name(data) => assert_eq!(data, document),
}
2025-07-28 10:49:34 -04:00
match msg.get_action() {
MsgAction::Create(_) => {}
_ => unreachable!("should have been a create document"),
}
}
}
#[test]
fn can_the_document_be_a_string() {
let dts = ["one".to_string(), "two".to_string()];
for document in dts.into_iter() {
2025-07-28 10:49:34 -04:00
let msg = Message::new(document.clone(), MsgAction::Query(Access::new()));
match msg.get_document_id() {
2025-07-17 09:12:23 -04:00
NameID::ID(_) => unreachable!("should have been a string id"),
NameID::Name(data) => assert_eq!(data, &document),
}
2025-07-28 10:49:34 -04:00
match msg.get_action() {
MsgAction::Query(_) => {}
_ => unreachable!("should have been an access query"),
}
}
}
#[test]
fn can_the_document_be_an_id() {
let document = Uuid::new_v4();
2025-07-28 10:49:34 -04:00
let msg = Message::new(document.clone(), MsgAction::Query(Access::new()));
match msg.get_document_id() {
2025-07-17 09:12:23 -04:00
NameID::ID(data) => assert_eq!(data, &document),
NameID::Name(_) => unreachable!("should have been an id"),
}
2025-07-28 10:49:34 -04:00
match msg.get_action() {
MsgAction::Query(_) => {}
_ => unreachable!("should have been an access query"),
}
}
#[test]
fn is_the_message_id_random() {
let mut ids: Vec<Uuid> = Vec::new();
for _ in 0..5 {
2025-07-28 10:49:34 -04:00
let msg = Message::new("tester", MsgAction::Create(DocDef::new()));
let id = msg.get_message_id().clone();
assert!(!ids.contains(&id), "{:?} containts {}", ids, id);
ids.push(id);
}
}
2025-07-17 09:12:23 -04:00
}
2025-07-25 11:08:47 -04:00
#[derive(Clone, Debug)]
2025-07-21 13:31:23 -04:00
enum Include<T> {
All,
Some(T),
}
impl<T: PartialEq> PartialEq for Include<T> {
fn eq(&self, other: &Self) -> bool {
match self {
Include::All => true,
Include::Some(data) => match other {
Include::All => true,
Include::Some(other_data) => data == other_data,
},
}
}
}
2025-07-25 11:08:47 -04:00
#[cfg(test)]
mod includes {
use super::*;
#[test]
fn does_all_equal_evberything() {
let a: Include<isize> = Include::All;
let b: Include<isize> = Include::Some(5);
let c: Include<isize> = Include::Some(7);
assert!(a == a, "all should equal all");
assert!(a == b, "all should equal some");
assert!(b == a, "some should equal all");
assert!(b == b, "same some should equal");
assert!(b != c, "different somes do not equal");
}
}
2025-07-17 09:12:23 -04:00
#[derive(Eq, Hash, PartialEq)]
2025-07-21 13:31:23 -04:00
struct RouteID {
2025-07-25 11:08:47 -04:00
action: Option<Action>,
2025-07-17 09:12:23 -04:00
doc_type: Option<Uuid>,
2025-07-25 11:08:47 -04:00
msg_id: Option<Uuid>,
2025-07-17 09:12:23 -04:00
}
2025-07-21 13:31:23 -04:00
impl From<Route> for RouteID {
2025-07-28 10:49:34 -04:00
fn from(value: Route) -> Self {
Self {
action: match value.action {
Include::All => None,
Include::Some(action) => Some(action.clone()),
},
doc_type: match value.doc_type {
Include::All => None,
Include::Some(doc) => Some(doc.clone()),
},
msg_id: match value.msg_id {
Include::All => None,
Include::Some(id) => Some(id.clone()),
},
}
2025-07-21 13:31:23 -04:00
}
}
2025-07-25 11:08:47 -04:00
#[derive(Clone, Debug, PartialEq)]
2025-07-21 13:31:23 -04:00
struct Route {
2025-07-25 11:08:47 -04:00
action: Include<Action>,
2025-07-21 13:31:23 -04:00
doc_type: Include<Uuid>,
2025-07-25 11:08:47 -04:00
msg_id: Include<Uuid>,
2025-07-21 13:31:23 -04:00
}
2025-07-17 09:12:23 -04:00
impl Route {
2025-07-28 10:49:34 -04:00
fn new(msg_id: Include<Uuid>, doc: Include<Uuid>, action: Include<Action>) -> Self {
2025-07-17 09:12:23 -04:00
Self {
action: action,
2025-07-25 11:08:47 -04:00
doc_type: doc,
msg_id: msg_id,
2025-07-17 09:12:23 -04:00
}
}
}
2025-07-21 13:31:23 -04:00
impl From<RouteID> for Route {
fn from(value: RouteID) -> Self {
Self {
2025-07-25 11:08:47 -04:00
action: match value.action {
Some(data) => Include::Some(data.clone()),
None => Include::All,
},
2025-07-21 13:31:23 -04:00
doc_type: match value.doc_type {
Some(doc) => Include::Some(doc.clone()),
None => Include::All,
},
2025-07-25 11:08:47 -04:00
msg_id: match value.msg_id {
Some(msg) => Include::Some(msg.clone()),
None => Include::All,
},
2025-07-21 13:31:23 -04:00
}
}
}
impl From<&RouteID> for Route {
fn from(value: &RouteID) -> Self {
Self {
2025-07-28 10:49:34 -04:00
action: match &value.action {
2025-07-25 11:08:47 -04:00
Some(data) => Include::Some(data.clone()),
None => Include::All,
},
doc_type: match &value.doc_type {
2025-07-21 13:31:23 -04:00
Some(doc) => Include::Some(doc.clone()),
None => Include::All,
},
2025-07-25 11:08:47 -04:00
msg_id: match &value.msg_id {
Some(msg) => Include::Some(msg.clone()),
None => Include::All,
},
}
}
}
#[cfg(test)]
mod roiutes {
use super::*;
#[test]
fn can_a_route_set_action() {
let actions = [Action::Query, Action::Reply];
for action in actions.into_iter() {
let route = Route::new(Include::All, Include::All, Include::Some(action.clone()));
match route.msg_id {
Include::All => {}
Include::Some(_) => unreachable!("should have been all"),
}
match route.doc_type {
Include::All => {}
Include::Some(_) => unreachable!("should have been all"),
}
match route.action {
Include::All => unreachable!("should be a specific value"),
Include::Some(result) => assert_eq!(result, action),
}
}
}
#[test]
fn can_route_set_document_by_name() {
let doc_id = Uuid::new_v4();
2025-07-28 10:49:34 -04:00
let route = Route::new(Include::All, Include::Some(doc_id.clone()), Include::All);
match route.msg_id {
Include::All => {}
Include::Some(_) => unreachable!("should have been all"),
}
match route.doc_type {
Include::All => unreachable!("should be a specific value"),
Include::Some(result) => assert_eq!(result, doc_id),
}
match route.action {
Include::All => {}
Include::Some(_) => unreachable!("should have been all"),
}
2025-07-25 11:08:47 -04:00
}
#[test]
fn can_route_set_document_by_id() {
let id = Uuid::new_v4();
let route = Route::new(Include::All, Include::Some(id.clone()), Include::All);
match route.msg_id {
Include::All => {}
Include::Some(_) => unreachable!("should have been all"),
}
match route.doc_type {
Include::All => unreachable!("should be a specific value"),
Include::Some(result) => assert_eq!(result, id),
}
match route.action {
Include::All => {}
Include::Some(_) => unreachable!("should have been all"),
}
}
#[test]
fn can_route_be_set_by_message_id() {
let id = Uuid::new_v4();
let route = Route::new(Include::Some(id.clone()), Include::All, Include::All);
match route.msg_id {
Include::All => unreachable!("should be a specific value"),
Include::Some(result) => assert_eq!(result, id),
}
match route.doc_type {
Include::All => {}
Include::Some(_) => unreachable!("should have been all"),
}
match route.action {
Include::All => {}
Include::Some(_) => unreachable!("should have been all"),
2025-07-21 13:31:23 -04:00
}
}
}
struct QueueData {
senders: HashMap<Uuid, Sender<Message>>,
names: HashMap<String, Uuid>,
2025-07-21 13:31:23 -04:00
routes: HashMap<RouteID, Vec<Uuid>>,
}
impl QueueData {
fn new() -> Self {
2025-07-17 09:12:23 -04:00
Self {
senders: HashMap::new(),
names: HashMap::new(),
2025-07-17 09:12:23 -04:00
routes: HashMap::new(),
}
}
2025-07-20 10:39:15 -04:00
fn get_doc_id<N>(&self, nameid: N) -> Result<Uuid, MTTError>
where
N: Into<NameID>,
{
let sender_id = match nameid.into() {
NameID::Name(name) => match self.names.get(&name) {
Some(id) => id.clone(),
None => return Err(MTTError::DocumentNotFound(name.clone())),
},
NameID::ID(id) => id.clone(),
};
if self.senders.contains_key(&sender_id) {
Ok(sender_id)
} else {
Err(MTTError::DocumentNotFound(sender_id.to_string()))
}
}
fn register(&mut self, name: String, tx: Sender<Message>) -> Result<Uuid, MTTError> {
2025-07-20 10:39:15 -04:00
match self.get_doc_id(name.as_str()) {
Ok(_) => return Err(MTTError::DocumentAlreadyExists(name)),
Err(_) => (),
2025-07-17 09:12:23 -04:00
}
let mut id = Uuid::new_v4();
while self.senders.contains_key(&id) {
id = Uuid::new_v4();
}
self.senders.insert(id.clone(), tx);
self.names.insert(name, id.clone());
Ok(id)
}
fn send(&self, msg: Message) -> Result<(), MTTError> {
2025-07-21 13:31:23 -04:00
let doc_id: Include<Uuid> = match self.get_doc_id(msg.get_document_id()) {
Ok(id) => Include::Some(id.clone()),
2025-07-25 11:08:47 -04:00
Err(err) => {
2025-07-28 10:49:34 -04:00
let action: Action = msg.get_action().into();
if action == Action::Create {
2025-07-25 11:08:47 -04:00
Include::Some(Uuid::nil())
} else {
2025-07-28 10:49:34 -04:00
return Err(err);
2025-07-25 11:08:47 -04:00
}
2025-07-28 10:49:34 -04:00
}
2025-07-17 09:12:23 -04:00
};
2025-07-28 10:49:34 -04:00
let route = Route::new(
Include::Some(msg.get_message_id().clone()),
doc_id,
Include::Some(msg.get_action().into()),
);
2025-07-21 13:31:23 -04:00
for (send_route, send_ids) in self.routes.iter() {
if route == send_route.into() {
for send_id in send_ids {
let tx = self.senders.get(&send_id).unwrap();
2025-07-20 10:39:15 -04:00
tx.send(msg.clone()).unwrap();
}
}
}
Ok(())
}
2025-07-17 09:12:23 -04:00
2025-07-20 10:39:15 -04:00
fn add_route<N>(
2025-07-17 09:12:23 -04:00
&mut self,
sender_id: &Uuid,
2025-07-21 13:31:23 -04:00
doc_type: Include<N>,
2025-07-17 09:12:23 -04:00
action: Action,
2025-07-20 10:39:15 -04:00
) -> Result<(), MTTError>
where
N: Into<NameID>,
{
2025-07-17 09:12:23 -04:00
let doc_id = match doc_type {
2025-07-21 13:31:23 -04:00
Include::Some(data) => match self.get_doc_id(data) {
Ok(id) => Include::Some(id.clone()),
2025-07-20 10:39:15 -04:00
Err(err) => return Err(err),
},
2025-07-21 13:31:23 -04:00
Include::All => Include::All,
2025-07-17 09:12:23 -04:00
};
2025-07-25 11:08:47 -04:00
let route = Route::new(Include::All, doc_id, Include::Some(action));
2025-07-21 13:31:23 -04:00
let route_id = route.into();
match self.routes.get_mut(&route_id) {
2025-07-20 10:39:15 -04:00
Some(mut senders) => senders.push(sender_id.clone()),
None => {
2025-07-21 13:31:23 -04:00
self.routes
.insert(route_id.into(), [sender_id.clone()].to_vec());
2025-07-20 10:39:15 -04:00
}
}
2025-07-17 09:12:23 -04:00
Ok(())
}
}
#[cfg(test)]
mod queuedatas {
use super::*;
2025-07-17 09:12:23 -04:00
use std::{sync::mpsc::RecvTimeoutError, time::Duration};
static TIMEOUT: Duration = Duration::from_millis(500);
#[test]
fn can_a_new_document_type_be_rgistered() {
let name = Uuid::new_v4().to_string();
2025-07-17 09:12:23 -04:00
let action = Action::Query;
let (tx, rx) = channel();
let mut queuedata = QueueData::new();
let id = queuedata.register(name.clone(), tx).unwrap();
2025-07-21 13:31:23 -04:00
queuedata.add_route(&id, Include::Some(name.clone()), action);
2025-07-28 10:49:34 -04:00
let msg = Message::new(name.clone(), MsgAction::Query(Access::new()));
queuedata.send(msg.clone()).unwrap();
let result = rx.recv_timeout(TIMEOUT).unwrap();
assert_eq!(result.get_message_id(), msg.get_message_id());
2025-07-28 10:49:34 -04:00
let msg = Message::new(id.clone(), MsgAction::Query(Access::new()));
queuedata.send(msg.clone()).unwrap();
let result = rx.recv_timeout(TIMEOUT).unwrap();
assert_eq!(result.get_message_id(), msg.get_message_id());
}
#[test]
fn does_a_bad_document_name_fail() {
let docname = Uuid::new_v4().to_string();
let queuedata = QueueData::new();
2025-07-28 10:49:34 -04:00
let msg = Message::new(docname.clone(), MsgAction::Query(Access::new()));
match queuedata.send(msg) {
Ok(_) => unreachable!("should have been an error"),
Err(data) => match data {
MTTError::DocumentNotFound(doc) => assert_eq!(doc, docname),
_ => unreachable!("should have been a not found error"),
},
}
}
#[test]
fn should_error_on_duplicate_name_registration() {
let name = Uuid::new_v4().to_string();
let (tx1, _) = channel();
let (tx2, _) = channel();
let mut queuedata = QueueData::new();
queuedata.register(name.clone(), tx1).unwrap();
match queuedata.register(name.clone(), tx2) {
Ok(_) => unreachable!("should have been an weeoe"),
Err(data) => match data {
MTTError::DocumentAlreadyExists(output) => assert_eq!(output, name),
_ => unreachable!("should have been an already exists errorr"),
},
}
}
2025-07-17 09:12:23 -04:00
#[test]
fn is_send_okay_if_no_one_is_listening() {
let mut queuedata = QueueData::new();
let name = "something";
let (tx, _) = channel();
queuedata.register(name.to_string(), tx).unwrap();
2025-07-28 10:49:34 -04:00
let msg = Message::new("something", MsgAction::Create(DocDef::new()));
2025-07-17 09:12:23 -04:00
match queuedata.send(msg) {
Ok(_) => {}
Err(err) => unreachable!("got {:?}: should not error", err),
}
}
#[test]
fn can_certain_messages_be_ignored() {
let mut queuedata = QueueData::new();
let doctype = "test";
let (tx, rx) = channel();
let id = queuedata.register(doctype.to_string(), tx).unwrap();
2025-07-21 13:31:23 -04:00
queuedata.add_route(&id, Include::Some(doctype.to_string()), Action::Query);
2025-07-28 10:49:34 -04:00
let msg = Message::new(doctype, MsgAction::Query(Access::new()));
2025-07-17 09:12:23 -04:00
queuedata.send(msg.clone()).unwrap();
let result = rx.recv_timeout(TIMEOUT).unwrap();
assert_eq!(result.get_message_id(), msg.get_message_id());
2025-07-28 10:49:34 -04:00
let msg = Message::new(doctype, MsgAction::Query(Access::new()));
2025-07-17 09:12:23 -04:00
match rx.recv_timeout(TIMEOUT) {
Ok(_) => unreachable!("should timeout"),
Err(err) => match err {
RecvTimeoutError::Timeout => {}
_ => unreachable!("should timeout"),
},
}
}
#[test]
2025-07-20 10:39:15 -04:00
fn can_more_than_one_document_respond() {
2025-07-17 09:12:23 -04:00
let mut queuedata = QueueData::new();
2025-07-20 10:39:15 -04:00
let name1 = "task";
let name2 = "work";
2025-07-28 10:49:34 -04:00
let action = MsgAction::Query(Access::new());
2025-07-17 09:12:23 -04:00
let (tx1, rx1) = channel();
let (tx2, rx2) = channel();
2025-07-20 10:39:15 -04:00
let id1 = queuedata.register(name1.to_string(), tx1).unwrap();
let id2 = queuedata.register(name2.to_string(), tx2).unwrap();
2025-07-28 10:49:34 -04:00
queuedata.add_route(
&id1,
Include::Some(name1.to_string()),
action.clone().into(),
);
queuedata.add_route(
&id2,
Include::Some(name1.to_string()),
action.clone().into(),
);
2025-07-20 10:39:15 -04:00
let msg = Message::new(name1, action.clone());
2025-07-17 09:12:23 -04:00
queuedata.send(msg.clone()).unwrap();
2025-07-20 10:39:15 -04:00
let result1 = rx1.recv_timeout(TIMEOUT).unwrap();
let result2 = rx2.recv_timeout(TIMEOUT).unwrap();
assert_eq!(result1.get_message_id(), msg.get_message_id());
assert_eq!(result1.get_message_id(), result2.get_message_id());
2025-07-17 09:12:23 -04:00
}
2025-07-21 13:31:23 -04:00
#[test]
fn can_a_route_be_generally_set() {
let mut queuedata = QueueData::new();
let doctype = "something";
2025-07-28 10:49:34 -04:00
let action = MsgAction::Query(Access::new());
2025-07-21 13:31:23 -04:00
let (tx, rx) = channel();
let id = queuedata.register(doctype.to_string(), tx).unwrap();
let data: Include<String> = Include::All;
2025-07-28 10:49:34 -04:00
queuedata.add_route(&id, data, action.clone().into());
2025-07-21 13:31:23 -04:00
let msg = Message::new(doctype, action);
queuedata.send(msg.clone()).unwrap();
let result = rx.recv_timeout(TIMEOUT).unwrap();
assert_eq!(result.get_message_id(), msg.get_message_id());
}
}
#[derive(Clone)]
struct Queue {
queue_data: Arc<RwLock<QueueData>>,
}
impl Queue {
fn new() -> Self {
Self {
queue_data: Arc::new(RwLock::new(QueueData::new())),
}
}
2025-07-25 11:08:47 -04:00
fn register(&mut self, name: String, tx: Sender<Message>) -> Result<Uuid, MTTError> {
let mut queuedata = self.queue_data.write().unwrap();
queuedata.register(name, tx)
}
fn send(&self, msg: Message) -> Result<(), MTTError> {
let queuedata = self.queue_data.read().unwrap();
queuedata.send(msg)
}
fn add_route<N>(
&mut self,
sender_id: &Uuid,
doc_type: Include<N>,
action: Action,
) -> Result<(), MTTError>
where
N: Into<NameID>,
{
let mut queuedata = self.queue_data.write().unwrap();
queuedata.add_route(sender_id, doc_type, action)
}
}
#[cfg(test)]
mod queues {
use super::*;
#[test]
fn create_a_queue() {
Queue::new();
}
}
2025-07-28 10:49:34 -04:00
struct CreateDoc {
queue: Queue,
rx: Receiver<Message>,
}
impl CreateDoc {
fn new(queue: Queue, rx: Receiver<Message>) -> Self {
Self {
queue: queue,
rx: rx,
}
}
fn start(mut queue: Queue) {
let (tx, rx) = channel();
let id = queue.register("document".to_string(), tx).unwrap();
let nameid: Include<NameID> = Include::All;
queue.add_route(&id, nameid, Action::Create);
let doc = CreateDoc::new(queue, rx);
spawn(move || {
doc.listen();
});
}
fn listen(&self) {
loop {
let msg = self.rx.recv().unwrap();
match msg.get_document_id() {
NameID::Name(name) => Document::start(self.queue.clone(), name.clone()),
NameID::ID(_) => unreachable!("should be a name"),
}
}
}
}
#[derive(Clone)]
struct DocDef;
impl DocDef {
fn new() -> Self {
Self {}
}
}
#[derive(Clone)]
struct Access;
impl Access {
fn new() -> Self {
Self {}
}
}
2025-07-25 11:08:47 -04:00
struct Document {
queue: Queue,
rx: Receiver<Message>,
}
impl Document {
2025-07-25 11:08:47 -04:00
fn new(queue: Queue, rx: Receiver<Message>) -> Self {
Self {
queue: queue,
rx: rx,
}
}
2025-07-28 10:49:34 -04:00
fn start(mut queue: Queue, name: String) {
2025-07-25 11:08:47 -04:00
let (tx, rx) = channel();
2025-07-28 10:49:34 -04:00
queue.register(name, tx);
2025-07-25 11:08:47 -04:00
let doc = Document::new(queue, rx);
spawn(move || {
doc.listen();
});
}
2025-07-25 11:08:47 -04:00
fn listen(&self) {
loop {
self.rx.recv().unwrap();
}
}
}
#[cfg(test)]
2025-07-28 10:49:34 -04:00
mod createdocs {
use super::*;
2025-07-28 10:49:34 -04:00
use std::{thread::sleep, time::Duration};
2025-07-28 10:49:34 -04:00
#[test]
fn create_document_creation() {
let queue = Queue::new();
2025-07-28 10:49:34 -04:00
CreateDoc::start(queue.clone());
2025-07-25 11:08:47 -04:00
let name = "project";
2025-07-28 10:49:34 -04:00
let msg = Message::new(name, MsgAction::Create(DocDef::new()));
2025-07-25 11:08:47 -04:00
queue.send(msg).unwrap();
2025-07-28 10:49:34 -04:00
sleep(Duration::from_secs(1));
let msg2 = Message::new(name, MsgAction::Query(Access::new()));
2025-07-25 11:08:47 -04:00
queue.send(msg2).unwrap();
}
}