event_notification/
store.rs

1use crate::Error;
2use crate::Log;
3use chrono::Utc;
4use std::sync::Arc;
5use tokio::fs::{File, OpenOptions, create_dir_all};
6use tokio::io::{AsyncBufReadExt, AsyncWriteExt, BufReader, BufWriter};
7use tokio::sync::RwLock;
8
9/// `EventStore` is a struct that manages the storage of event logs.
10pub struct EventStore {
11    path: String,
12    lock: Arc<RwLock<()>>,
13}
14
15impl EventStore {
16    pub async fn new(path: &str) -> Result<Self, Error> {
17        create_dir_all(path).await?;
18        Ok(Self {
19            path: path.to_string(),
20            lock: Arc::new(RwLock::new(())),
21        })
22    }
23
24    pub async fn save_logs(&self, logs: &[Log]) -> Result<(), Error> {
25        let _guard = self.lock.write().await;
26        let file_path = format!("{}/events_{}.jsonl", self.path, Utc::now().timestamp());
27        let file = OpenOptions::new()
28            .create(true)
29            .append(true)
30            .open(&file_path)
31            .await?;
32        let mut writer = BufWriter::new(file);
33        for log in logs {
34            let line = serde_json::to_string(log)?;
35            writer.write_all(line.as_bytes()).await?;
36            writer.write_all(b"\n").await?;
37        }
38        writer.flush().await?;
39        Ok(())
40    }
41
42    pub async fn load_logs(&self) -> Result<Vec<Log>, Error> {
43        let _guard = self.lock.read().await;
44        let mut logs = Vec::new();
45        let mut entries = tokio::fs::read_dir(&self.path).await?;
46        while let Some(entry) = entries.next_entry().await? {
47            let file = File::open(entry.path()).await?;
48            let reader = BufReader::new(file);
49            let mut lines = reader.lines();
50            while let Some(line) = lines.next_line().await? {
51                let log: Log = serde_json::from_str(&line)?;
52                logs.push(log);
53            }
54        }
55        Ok(logs)
56    }
57}