event_notification/
store.rs1use 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
9pub 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}