1#![deny(missing_docs)]
2#![deny(rust_2018_idioms)]
3#![deny(rustdoc::broken_intra_doc_links)]
4
5mod jobs;
34mod kv;
35mod pubsub;
36mod request_reply;
37
38pub use jobs::MemoryJobQueue;
39pub use kv::MemoryKv;
40pub use pubsub::MemoryPubsub;
41pub use request_reply::MemoryRequestReply;
42
43use klieo_core::{BusHandles, JobQueue, KvStore, Pubsub, RequestReply};
44use std::sync::Arc;
45
46pub struct MemoryBus {
48 pub pubsub: Arc<dyn Pubsub>,
50 pub request_reply: Arc<dyn RequestReply>,
52 pub kv: Arc<dyn KvStore>,
54 pub jobs: Arc<dyn JobQueue>,
56}
57
58impl MemoryBus {
59 pub fn new() -> Self {
61 let pubsub_concrete = Arc::new(MemoryPubsub::new());
62 let kv_concrete = Arc::new(MemoryKv::new());
63 let rr_concrete = Arc::new(MemoryRequestReply::new(pubsub_concrete.clone()));
64 let jobs_concrete = Arc::new(MemoryJobQueue::new(
65 pubsub_concrete.clone(),
66 kv_concrete.clone(),
67 ));
68 Self {
69 pubsub: pubsub_concrete,
70 request_reply: rr_concrete,
71 kv: kv_concrete,
72 jobs: jobs_concrete,
73 }
74 }
75
76 pub fn shared() -> Arc<Self> {
84 Arc::new(Self::new())
85 }
86}
87
88impl Default for MemoryBus {
89 fn default() -> Self {
90 Self::new()
91 }
92}
93
94impl From<MemoryBus> for BusHandles {
95 fn from(value: MemoryBus) -> Self {
96 BusHandles::new(value.pubsub, value.kv, value.request_reply, value.jobs)
97 }
98}
99
100#[cfg(test)]
101mod lib_tests {
102 use super::*;
103 use bytes::Bytes;
104 use klieo_core::bus::{Headers, Job};
105 use klieo_core::ids::DurableName;
106 use std::time::Duration;
107 use tokio_stream::StreamExt;
108
109 #[tokio::test]
110 async fn shared_returns_arc_wired_and_usable() {
111 let bus = MemoryBus::shared();
112 bus.kv
113 .put("b", "k", Bytes::from_static(b"shared"))
114 .await
115 .unwrap();
116 let entry = bus.kv.get("b", "k").await.unwrap().unwrap();
117 assert_eq!(entry.value, Bytes::from_static(b"shared"));
118 let bus2 = Arc::clone(&bus);
120 let entry2 = bus2.kv.get("b", "k").await.unwrap().unwrap();
121 assert_eq!(entry2.value, Bytes::from_static(b"shared"));
122 }
123
124 #[tokio::test]
125 async fn memory_bus_wires_all_four() {
126 let bus = MemoryBus::new();
127 bus.kv
128 .put("b", "k", Bytes::from_static(b"v"))
129 .await
130 .unwrap();
131 let entry = bus.kv.get("b", "k").await.unwrap().unwrap();
132 assert_eq!(entry.value, Bytes::from_static(b"v"));
133 let mut sub = bus
134 .pubsub
135 .subscribe("s", DurableName::new("d"))
136 .await
137 .unwrap();
138 bus.pubsub
139 .publish("s", Bytes::from_static(b"hi"), Headers::new())
140 .await
141 .unwrap();
142 let msg = sub.next().await.unwrap().unwrap();
143 assert_eq!(msg.payload, Bytes::from_static(b"hi"));
144 let err = bus
145 .request_reply
146 .request("svc", Bytes::from_static(b"x"), Duration::from_millis(20))
147 .await
148 .unwrap_err();
149 assert!(matches!(err, klieo_core::BusError::Timeout));
150 let id = bus
151 .jobs
152 .enqueue("q", Job::new(Bytes::from_static(b"j")))
153 .await
154 .unwrap();
155 let claimed = bus
156 .jobs
157 .claim("q", "w", Duration::from_secs(1))
158 .await
159 .unwrap()
160 .unwrap();
161 assert_eq!(claimed.id, id);
162 }
163
164 #[tokio::test]
165 async fn bus_handles_from_memory_bus_preserves_handles() {
166 let bus = MemoryBus::new();
167 let ps = Arc::as_ptr(&bus.pubsub);
168 let kv = Arc::as_ptr(&bus.kv);
169 let rr = Arc::as_ptr(&bus.request_reply);
170 let jq = Arc::as_ptr(&bus.jobs);
171 let handles: BusHandles = bus.into();
172 assert!(std::ptr::addr_eq(Arc::as_ptr(&handles.pubsub), ps));
173 assert!(std::ptr::addr_eq(Arc::as_ptr(&handles.kv), kv));
174 assert!(std::ptr::addr_eq(Arc::as_ptr(&handles.request_reply), rr));
175 assert!(std::ptr::addr_eq(Arc::as_ptr(&handles.jobs), jq));
176 }
177}