Skip to main content

rskit_messaging/
memory.rs

1//! In-memory message broker, producer, and consumer for testing.
2
3use std::collections::{HashSet, VecDeque};
4use std::sync::Arc;
5use std::time::Duration;
6
7use async_trait::async_trait;
8use rskit_errors::{AppError, AppResult, ErrorCode};
9use tokio::sync::{Mutex, broadcast};
10
11use crate::config::BrokerConfig;
12use crate::event::Event;
13use crate::message::Message;
14use crate::registry::{MessagingFactory, MessagingRegistry};
15use crate::traits::{EventConsumer, EventProducer, MessageConsumer, MessageProducer};
16
17const ADAPTER_NAME: &str = "memory";
18
19/// An in-memory message broker backed by a `tokio::sync::broadcast` channel.
20///
21/// Create one broker and hand out producers / consumers via
22/// [`InMemoryBroker::producer`] and [`InMemoryBroker::consumer`].
23///
24/// Every message sent through the broker is recorded in an internal history
25/// so that test assertion helpers can inspect what was published.
26#[derive(Debug, Clone)]
27pub struct InMemoryBroker<T: Clone + Send + Sync + 'static> {
28    tx: broadcast::Sender<Message<T>>,
29    history: Arc<Mutex<VecDeque<Message<T>>>>,
30    history_limit: Option<usize>,
31    topics: Arc<Mutex<HashSet<String>>>,
32    /// Notified after every publish so that [`wait_for_message`] can wake
33    /// without polling.
34    notify: Arc<tokio::sync::Notify>,
35}
36
37impl<T: Clone + Send + Sync + 'static> InMemoryBroker<T> {
38    /// Create a broker with the given channel capacity.
39    pub fn new(capacity: usize) -> Self {
40        let limit = capacity.max(1);
41        let (tx, _) = broadcast::channel(limit);
42        Self {
43            tx,
44            history: Arc::new(Mutex::new(VecDeque::with_capacity(limit))),
45            history_limit: Some(limit),
46            topics: Arc::new(Mutex::new(HashSet::new())),
47            notify: Arc::new(tokio::sync::Notify::new()),
48        }
49    }
50
51    /// Create a producer attached to this broker.
52    pub fn producer(&self) -> InMemoryProducer<T> {
53        InMemoryProducer {
54            tx: self.tx.clone(),
55            history: self.history.clone(),
56            history_limit: self.history_limit,
57            topics: self.topics.clone(),
58            notify: self.notify.clone(),
59        }
60    }
61
62    /// Create a broker with explicit channel capacity and bounded history limit.
63    ///
64    /// The default [`InMemoryBroker::new`] bounds history by channel capacity. Use this
65    /// constructor when tests need a different history limit.
66    #[must_use]
67    pub fn with_history_limit(capacity: usize, history_limit: usize) -> Self {
68        let capacity = capacity.max(1);
69        let limit = history_limit.max(1);
70        let (tx, _) = broadcast::channel(capacity);
71        Self {
72            tx,
73            history: Arc::new(Mutex::new(VecDeque::with_capacity(limit))),
74            history_limit: Some(limit),
75            topics: Arc::new(Mutex::new(HashSet::new())),
76            notify: Arc::new(tokio::sync::Notify::new()),
77        }
78    }
79
80    /// Create a consumer attached to this broker.
81    pub fn consumer(&self) -> InMemoryConsumer<T> {
82        InMemoryConsumer {
83            rx: Arc::new(Mutex::new(self.tx.subscribe())),
84            topics: Arc::new(Mutex::new(HashSet::new())),
85        }
86    }
87
88    /// Return a clone of all messages published to `topic`.
89    pub async fn messages(&self, topic: &str) -> Vec<Message<T>> {
90        self.history
91            .lock()
92            .await
93            .iter()
94            .filter(|m| m.topic == topic)
95            .cloned()
96            .collect()
97    }
98
99    /// Return a clone of every message published to any topic.
100    pub async fn all_messages(&self) -> Vec<Message<T>> {
101        self.history.lock().await.iter().cloned().collect()
102    }
103
104    /// Return the number of messages published to `topic`.
105    pub async fn message_count(&self, topic: &str) -> usize {
106        self.history
107            .lock()
108            .await
109            .iter()
110            .filter(|m| m.topic == topic)
111            .count()
112    }
113
114    /// Clear the recorded message history.
115    pub async fn reset(&self) {
116        self.history.lock().await.clear();
117    }
118
119    /// Pre-create a topic so that it appears in [`InMemoryBroker::topic_names`].
120    pub async fn create_topic(&self, topic: &str) {
121        self.topics.lock().await.insert(topic.to_string());
122    }
123
124    /// Return the sorted set of topic names that have been created or published to.
125    pub async fn topic_names(&self) -> Vec<String> {
126        let mut set: HashSet<String> = self.topics.lock().await.clone();
127        {
128            let hist = self.history.lock().await;
129            for m in hist.iter() {
130                set.insert(m.topic.clone());
131            }
132        }
133        let mut out: Vec<String> = set.into_iter().collect();
134        out.sort();
135        out
136    }
137}
138
139impl<T: Clone + Send + Sync + 'static> Default for InMemoryBroker<T> {
140    fn default() -> Self {
141        Self::new(256)
142    }
143}
144
145/// Register in-memory producer and consumer factories.
146pub fn register<T: Clone + Send + Sync + 'static>(
147    registry: &mut MessagingRegistry<T>,
148    broker: InMemoryBroker<T>,
149) -> AppResult<()> {
150    registry.register_backend(ADAPTER_NAME, Arc::new(MemoryFactory { broker }))
151}
152
153struct MemoryFactory<T: Clone + Send + Sync + 'static> {
154    broker: InMemoryBroker<T>,
155}
156
157impl<T: Clone + Send + Sync + 'static> MessagingFactory<T> for MemoryFactory<T> {
158    fn create_producer(&self, _config: &BrokerConfig) -> AppResult<Arc<dyn MessageProducer<T>>> {
159        Ok(Arc::new(self.broker.producer()))
160    }
161
162    fn create_consumer(&self, _config: &BrokerConfig) -> AppResult<Arc<dyn MessageConsumer<T>>> {
163        Ok(Arc::new(self.broker.consumer()))
164    }
165}
166
167/// An in-memory message producer.
168#[derive(Debug, Clone)]
169pub struct InMemoryProducer<T: Clone + Send + Sync + 'static> {
170    tx: broadcast::Sender<Message<T>>,
171    history: Arc<Mutex<VecDeque<Message<T>>>>,
172    history_limit: Option<usize>,
173    topics: Arc<Mutex<HashSet<String>>>,
174    notify: Arc<tokio::sync::Notify>,
175}
176
177#[async_trait]
178impl<T: Clone + Send + Sync + 'static> MessageProducer<T> for InMemoryProducer<T> {
179    async fn send(&self, msg: Message<T>) -> AppResult<()> {
180        // Record in history before broadcasting.
181        {
182            let mut hist = self.history.lock().await;
183            if let Some(limit) = self.history_limit
184                && hist.len() == limit
185            {
186                hist.pop_front();
187            }
188            hist.push_back(msg.clone());
189        }
190        {
191            let mut set = self.topics.lock().await;
192            set.insert(msg.topic.clone());
193        }
194
195        self.tx.send(msg).map_err(|_| {
196            AppError::new(ErrorCode::ExternalService, "no active consumers on channel")
197        })?;
198
199        self.notify.notify_waiters();
200        Ok(())
201    }
202
203    async fn send_batch(&self, msgs: Vec<Message<T>>) -> AppResult<()> {
204        for msg in msgs {
205            self.send(msg).await?;
206        }
207        Ok(())
208    }
209
210    async fn flush(&self, _timeout: Duration) -> AppResult<()> {
211        // In-memory delivery is instant; nothing to flush.
212        Ok(())
213    }
214}
215
216/// An in-memory message consumer.
217#[derive(Debug)]
218pub struct InMemoryConsumer<T: Clone + Send + Sync + 'static> {
219    rx: Arc<Mutex<broadcast::Receiver<Message<T>>>>,
220    topics: Arc<Mutex<HashSet<String>>>,
221}
222
223// Manual Clone because broadcast::Receiver is not Clone but we can resubscribe.
224impl<T: Clone + Send + Sync + 'static> Clone for InMemoryConsumer<T> {
225    fn clone(&self) -> Self {
226        Self {
227            rx: self.rx.clone(),
228            topics: self.topics.clone(),
229        }
230    }
231}
232
233#[async_trait]
234impl<T: Clone + Send + Sync + 'static> MessageConsumer<T> for InMemoryConsumer<T> {
235    async fn subscribe(&self, topics: &[&str]) -> AppResult<()> {
236        {
237            let mut set = self.topics.lock().await;
238            for t in topics {
239                set.insert((*t).to_string());
240            }
241        }
242        Ok(())
243    }
244
245    async fn recv(&self, timeout: std::time::Duration) -> AppResult<Message<T>> {
246        if timeout.is_zero() {
247            return Err(AppError::new(
248                ErrorCode::InvalidInput,
249                "message receive timeout must be greater than zero",
250            ));
251        }
252        tokio::time::timeout(timeout, async {
253            loop {
254                let msg = {
255                    let mut rx = self.rx.lock().await;
256                    rx.recv().await.map_err(|e| {
257                        AppError::new(ErrorCode::ExternalService, format!("receive failed: {e}"))
258                    })?
259                };
260
261                let topics = self.topics.lock().await;
262                // If no explicit subscription, accept all messages.
263                if topics.is_empty() || topics.contains(&msg.topic) {
264                    return Ok(msg);
265                }
266                // Otherwise loop to skip messages for other topics.
267            }
268        })
269        .await
270        .map_err(|error| AppError::timeout("message receive").with_cause(error))?
271    }
272}
273
274#[async_trait]
275impl EventProducer for InMemoryProducer<serde_json::Value> {
276    async fn publish(&self, topic: &str, event: Event) -> AppResult<()> {
277        let value = serde_json::to_value(&event).map_err(|e| {
278            AppError::new(
279                ErrorCode::Internal,
280                format!("Failed to serialize event: {e}"),
281            )
282        })?;
283        self.send(Message::new(topic, value)).await
284    }
285
286    async fn publish_batch(&self, topic: &str, events: Vec<Event>) -> AppResult<()> {
287        for event in events {
288            self.publish(topic, event).await?;
289        }
290        Ok(())
291    }
292}
293
294#[async_trait]
295impl EventConsumer for InMemoryConsumer<serde_json::Value> {
296    async fn subscribe(&self, topics: &[&str]) -> AppResult<()> {
297        MessageConsumer::subscribe(self, topics).await
298    }
299
300    async fn recv_event(&self, timeout: std::time::Duration) -> AppResult<Event> {
301        let msg = self.recv(timeout).await?;
302        serde_json::from_value(msg.payload).map_err(|e| {
303            AppError::new(
304                ErrorCode::Internal,
305                format!("Failed to deserialize event: {e}"),
306            )
307        })
308    }
309}
310
311/// Assert that at least one message on `topic` satisfies the predicate.
312///
313/// # Panics
314///
315/// Panics when no matching message is found.
316pub async fn assert_published<T: Clone + Send + Sync + 'static>(
317    broker: &InMemoryBroker<T>,
318    topic: &str,
319    predicate: impl Fn(&Message<T>) -> bool,
320) {
321    let msgs = broker.messages(topic).await;
322    assert!(
323        msgs.iter().any(&predicate),
324        "assert_published: no message on topic {topic:?} matched the predicate ({} checked)",
325        msgs.len(),
326    );
327}
328
329/// Assert that exactly `n` messages were published to `topic`.
330///
331/// # Panics
332///
333/// Panics when the count does not match.
334pub async fn assert_published_n<T: Clone + Send + Sync + 'static>(
335    broker: &InMemoryBroker<T>,
336    topic: &str,
337    n: usize,
338) {
339    let got = broker.message_count(topic).await;
340    assert_eq!(
341        got, n,
342        "assert_published_n: topic {topic:?} has {got} messages, want {n}",
343    );
344}
345
346/// Wait until at least one message appears on `topic` or the timeout expires.
347///
348/// Returns the first message on the topic.
349///
350/// # Panics
351///
352/// Panics if the timeout elapses before any message arrives.
353pub async fn wait_for_message<T: Clone + Send + Sync + 'static>(
354    broker: &InMemoryBroker<T>,
355    topic: &str,
356    timeout: Duration,
357) -> Message<T> {
358    let deadline = tokio::time::Instant::now() + timeout;
359
360    loop {
361        let msgs = broker.messages(topic).await;
362        if let Some(m) = msgs.into_iter().next() {
363            return m;
364        }
365        tokio::select! {
366            () = broker.notify.notified() => { /* re-check */ }
367            () = tokio::time::sleep_until(deadline) => {
368                panic!("wait_for_message: timed out after {timeout:?} waiting for message on topic {topic:?}");
369            }
370        }
371    }
372}
373
374/// Assert that zero messages were published to `topic`.
375///
376/// # Panics
377///
378/// Panics when the topic is not empty.
379pub async fn assert_no_messages<T: Clone + Send + Sync + 'static>(
380    broker: &InMemoryBroker<T>,
381    topic: &str,
382) {
383    let n = broker.message_count(topic).await;
384    assert_eq!(
385        n, 0,
386        "assert_no_messages: topic {topic:?} has {n} messages, want 0",
387    );
388}
389
390#[cfg(test)]
391mod tests {
392    use super::*;
393
394    #[tokio::test]
395    async fn send_and_receive() {
396        let broker: InMemoryBroker<String> = InMemoryBroker::new(16);
397        let producer = broker.producer();
398        let consumer = broker.consumer();
399
400        consumer.subscribe(&["test-topic"]).await.unwrap();
401
402        let msg = Message::new("test-topic", "hello".to_string());
403        producer.send(msg).await.unwrap();
404
405        let received = consumer
406            .recv(std::time::Duration::from_secs(1))
407            .await
408            .unwrap();
409        assert_eq!(received.topic, "test-topic");
410        assert_eq!(received.payload, "hello");
411    }
412
413    #[tokio::test]
414    async fn register_memory_adapter_explicitly() {
415        let broker: InMemoryBroker<String> = InMemoryBroker::new(16);
416        let mut registry = MessagingRegistry::new();
417
418        register(&mut registry, broker).unwrap();
419
420        assert_eq!(registry.adapters(), vec!["memory"]);
421        let config = BrokerConfig::default();
422        let producer = registry.producer(&config).unwrap();
423        let consumer = registry.consumer(&config).unwrap();
424        consumer.subscribe(&["events"]).await.unwrap();
425        producer
426            .send(Message::new("events", "registered".to_string()))
427            .await
428            .unwrap();
429        let received = consumer
430            .recv(std::time::Duration::from_secs(1))
431            .await
432            .unwrap();
433        assert_eq!(received.payload, "registered");
434    }
435
436    #[tokio::test]
437    async fn send_batch_and_receive() {
438        let broker: InMemoryBroker<i32> = InMemoryBroker::new(16);
439        let producer = broker.producer();
440        let consumer = broker.consumer();
441
442        consumer.subscribe(&["numbers"]).await.unwrap();
443
444        let msgs = vec![
445            Message::new("numbers", 1),
446            Message::new("numbers", 2),
447            Message::new("numbers", 3),
448        ];
449        producer.send_batch(msgs).await.unwrap();
450
451        let a = consumer
452            .recv(std::time::Duration::from_secs(1))
453            .await
454            .unwrap();
455        let b = consumer
456            .recv(std::time::Duration::from_secs(1))
457            .await
458            .unwrap();
459        let c = consumer
460            .recv(std::time::Duration::from_secs(1))
461            .await
462            .unwrap();
463        assert_eq!(a.payload, 1);
464        assert_eq!(b.payload, 2);
465        assert_eq!(c.payload, 3);
466    }
467
468    #[tokio::test]
469    async fn topic_filtering() {
470        let broker: InMemoryBroker<String> = InMemoryBroker::new(16);
471        let producer = broker.producer();
472        let consumer = broker.consumer();
473
474        consumer.subscribe(&["wanted"]).await.unwrap();
475
476        producer
477            .send(Message::new("ignored", "nope".to_string()))
478            .await
479            .unwrap();
480        producer
481            .send(Message::new("wanted", "yes".to_string()))
482            .await
483            .unwrap();
484
485        let received = consumer
486            .recv(std::time::Duration::from_secs(1))
487            .await
488            .unwrap();
489        assert_eq!(received.topic, "wanted");
490        assert_eq!(received.payload, "yes");
491    }
492
493    #[tokio::test]
494    async fn flush_is_noop() {
495        let broker: InMemoryBroker<()> = InMemoryBroker::new(4);
496        let producer = broker.producer();
497        producer.flush(Duration::from_secs(1)).await.unwrap();
498    }
499
500    #[tokio::test]
501    async fn event_publish_and_receive() {
502        let broker: InMemoryBroker<serde_json::Value> = InMemoryBroker::new(16);
503        let producer = broker.producer();
504        let consumer = broker.consumer();
505
506        EventConsumer::subscribe(&consumer, &["events"])
507            .await
508            .unwrap();
509
510        let event = Event::new("user.created", "auth-service")
511            .with_subject("user-42")
512            .with_data(serde_json::json!({"name": "Alice"}))
513            .unwrap();
514        let original_id = event.id.clone();
515
516        producer.publish("events", event).await.unwrap();
517
518        let received = consumer
519            .recv_event(std::time::Duration::from_secs(1))
520            .await
521            .unwrap();
522        assert_eq!(received.id, original_id);
523        assert_eq!(received.event_type, "user.created");
524        assert_eq!(received.source, "auth-service");
525        assert_eq!(received.subject, "user-42");
526        assert_eq!(received.data, serde_json::json!({"name": "Alice"}));
527    }
528
529    #[tokio::test]
530    async fn event_publish_batch_and_receive() {
531        let broker: InMemoryBroker<serde_json::Value> = InMemoryBroker::new(16);
532        let producer = broker.producer();
533        let consumer = broker.consumer();
534
535        EventConsumer::subscribe(&consumer, &["batch"])
536            .await
537            .unwrap();
538
539        let events = vec![
540            Event::new("a", "src"),
541            Event::new("b", "src"),
542            Event::new("c", "src"),
543        ];
544        producer.publish_batch("batch", events).await.unwrap();
545
546        let a = consumer
547            .recv_event(std::time::Duration::from_secs(1))
548            .await
549            .unwrap();
550        let b = consumer
551            .recv_event(std::time::Duration::from_secs(1))
552            .await
553            .unwrap();
554        let c = consumer
555            .recv_event(std::time::Duration::from_secs(1))
556            .await
557            .unwrap();
558        assert_eq!(a.event_type, "a");
559        assert_eq!(b.event_type, "b");
560        assert_eq!(c.event_type, "c");
561    }
562
563    // ── History & topic helper tests ────────────────────────────────────────
564
565    #[tokio::test]
566    async fn messages_returns_topic_history() {
567        let broker: InMemoryBroker<String> = InMemoryBroker::new(16);
568        let producer = broker.producer();
569        // Need a consumer so broadcast::send succeeds.
570        let _consumer = broker.consumer();
571
572        producer
573            .send(Message::new("t1", "a".to_string()))
574            .await
575            .unwrap();
576        producer
577            .send(Message::new("t1", "b".to_string()))
578            .await
579            .unwrap();
580        producer
581            .send(Message::new("t2", "c".to_string()))
582            .await
583            .unwrap();
584
585        let t1 = broker.messages("t1").await;
586        assert_eq!(t1.len(), 2);
587        assert_eq!(t1[0].payload, "a");
588        assert_eq!(t1[1].payload, "b");
589
590        let all = broker.all_messages().await;
591        assert_eq!(all.len(), 3);
592    }
593
594    #[tokio::test]
595    async fn in_memory_history_is_bounded() {
596        let broker = InMemoryBroker::with_history_limit(8, 2);
597        let producer = broker.producer();
598        let _consumer = broker.consumer();
599
600        producer.send(Message::new("events", 1_u32)).await.unwrap();
601        producer.send(Message::new("events", 2_u32)).await.unwrap();
602        producer.send(Message::new("events", 3_u32)).await.unwrap();
603
604        let messages = broker.messages("events").await;
605        assert_eq!(messages.len(), 2);
606        assert_eq!(messages[0].payload, 2);
607        assert_eq!(messages[1].payload, 3);
608    }
609
610    #[tokio::test]
611    async fn message_count_and_reset() {
612        let broker: InMemoryBroker<i32> = InMemoryBroker::new(16);
613        let producer = broker.producer();
614        let _consumer = broker.consumer();
615
616        assert_eq!(broker.message_count("t").await, 0);
617        producer.send(Message::new("t", 1)).await.unwrap();
618        assert_eq!(broker.message_count("t").await, 1);
619
620        broker.reset().await;
621        assert_eq!(broker.message_count("t").await, 0);
622    }
623
624    #[tokio::test]
625    async fn create_topic_and_topic_names() {
626        let broker: InMemoryBroker<String> = InMemoryBroker::new(16);
627        let _consumer = broker.consumer();
628
629        broker.create_topic("z-topic").await;
630        broker.create_topic("a-topic").await;
631
632        producer_send_helper(&broker, "m-topic").await;
633
634        let names = broker.topic_names().await;
635        assert_eq!(names, vec!["a-topic", "m-topic", "z-topic"]);
636    }
637
638    /// Helper: send a dummy message so that the topic appears in history.
639    async fn producer_send_helper(broker: &InMemoryBroker<String>, topic: &str) {
640        let producer = broker.producer();
641        producer
642            .send(Message::new(topic, "x".to_string()))
643            .await
644            .unwrap();
645    }
646
647    // ── Assertion helper tests ──────────────────────────────────────────────
648
649    #[tokio::test]
650    async fn test_assert_published() {
651        let broker: InMemoryBroker<String> = InMemoryBroker::new(16);
652        let producer = broker.producer();
653        let _consumer = broker.consumer();
654
655        producer
656            .send(Message::new("t1", "hello".to_string()))
657            .await
658            .unwrap();
659        producer
660            .send(Message::new("t1", "world".to_string()))
661            .await
662            .unwrap();
663
664        assert_published(&broker, "t1", |m| m.payload == "world").await;
665    }
666
667    #[tokio::test]
668    async fn test_assert_published_n() {
669        let broker: InMemoryBroker<String> = InMemoryBroker::new(16);
670        let producer = broker.producer();
671        let _consumer = broker.consumer();
672
673        producer
674            .send(Message::new("t1", "a".to_string()))
675            .await
676            .unwrap();
677        producer
678            .send(Message::new("t1", "b".to_string()))
679            .await
680            .unwrap();
681
682        assert_published_n(&broker, "t1", 2).await;
683    }
684
685    #[tokio::test]
686    async fn test_assert_no_messages() {
687        let broker: InMemoryBroker<String> = InMemoryBroker::new(16);
688        assert_no_messages(&broker, "empty-topic").await;
689    }
690
691    #[tokio::test]
692    async fn test_wait_for_message() {
693        let broker: InMemoryBroker<String> = InMemoryBroker::new(16);
694        let _consumer = broker.consumer();
695
696        let broker_clone = broker.clone();
697        tokio::spawn(async move {
698            tokio::time::sleep(Duration::from_millis(20)).await;
699            let producer = broker_clone.producer();
700            producer
701                .send(Message::new("t1", "delayed".to_string()))
702                .await
703                .unwrap();
704        });
705
706        let msg = wait_for_message(&broker, "t1", Duration::from_secs(2)).await;
707        assert_eq!(msg.payload, "delayed");
708    }
709    #[tokio::test]
710    async fn default_history_is_bounded_by_capacity() {
711        let broker: InMemoryBroker<usize> = InMemoryBroker::new(8);
712        let producer = broker.producer();
713        let _consumer = broker.consumer();
714
715        for value in 0..1030 {
716            producer.send(Message::new("history", value)).await.unwrap();
717        }
718
719        let messages = broker.messages("history").await;
720        assert_eq!(messages.len(), 8);
721        assert_eq!(messages.first().map(|msg| msg.payload), Some(1022));
722    }
723
724    #[tokio::test]
725    async fn bounded_history_limit_is_opt_in() {
726        let broker: InMemoryBroker<usize> = InMemoryBroker::with_history_limit(8, 2);
727        let producer = broker.producer();
728        let _consumer = broker.consumer();
729
730        for value in 0..4 {
731            producer.send(Message::new("history", value)).await.unwrap();
732        }
733
734        let payloads = broker
735            .messages("history")
736            .await
737            .into_iter()
738            .map(|msg| msg.payload)
739            .collect::<Vec<_>>();
740        assert_eq!(payloads, vec![2, 3]);
741    }
742
743    #[tokio::test]
744    async fn zero_capacity_is_clamped() {
745        let broker: InMemoryBroker<usize> = InMemoryBroker::new(0);
746        let producer = broker.producer();
747        let _consumer = broker.consumer();
748
749        producer.send(Message::new("history", 1)).await.unwrap();
750
751        let messages = broker.messages("history").await;
752        assert_eq!(messages.len(), 1);
753    }
754}