1use std::{collections::VecDeque, sync::Arc};
2
3use async_trait::async_trait;
4use tokio::sync::Mutex;
5
6use crate::{backend::Backend, Log};
7
8#[derive(Debug)]
10pub struct Memory {
11 pub max_entries: usize,
13 pub entries: Arc<Mutex<VecDeque<Log>>>,
15}
16
17impl Memory {
18 #[must_use]
20 pub fn new(max_entries: usize) -> Self {
21 Self {
22 max_entries,
23 entries: Arc::default(),
24 }
25 }
26}
27
28#[async_trait]
29impl Backend for Memory {
30 async fn process_log(&mut self, log: &Log) -> anyhow::Result<()> {
31 let mut entries = self.entries.lock().await;
32
33 entries.push_front(log.clone());
34
35 while entries.len() > self.max_entries {
36 entries.pop_back();
37 }
38
39 Ok(())
40 }
41}
42
43#[cfg(test)]
44mod tests {
45 use std::time::Duration;
46
47 use crate::{Configuration, Manager};
48
49 use super::*;
50
51 #[tokio::test]
52 async fn send_test() -> anyhow::Result<()> {
53 let test_backend = Memory::new(2);
54 let entries = test_backend.entries.clone();
55 let sender = Manager::default()
56 .with_backend(test_backend)
57 .launch(|task| {
58 tokio::spawn(task);
59 });
60
61 Configuration::named("send_test", sender)
62 .run(async {
63 Log::info("A").submit();
64 Log::info("B").submit();
65 Log::info("A").submit();
66 })
67 .await;
68
69 tokio::time::sleep(Duration::from_millis(1)).await;
70 {
71 let entries = entries.lock().await;
72 assert_eq!(entries.len(), 2);
73 assert_eq!(entries[0].message, "A");
74 assert_eq!(entries[1].message, "B");
75 }
76
77 Ok(())
78 }
79}