Skip to content

Commit 42b78e7

Browse files
committed
fix: Add log as newline-delimited json
1 parent 786b5f3 commit 42b78e7

File tree

4 files changed

+121
-1
lines changed

4 files changed

+121
-1
lines changed

Cargo.lock

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,3 +68,6 @@ toml = { version = "0.9.5", features = ["preserve_order"] }
6868
uucore = { version = "0.1.0", features = ["fsext"] }
6969
# Finding XDG standard directories (such as ~/.config/torrentmanager/config.toml)
7070
xdg = "3.0.0"
71+
72+
[dev-dependencies]
73+
async-tempfile = "0.7"

src/extractors/user.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use serde::{Deserialize, Serialize};
1010
/// Cannot be produced outside of header extraction.
1111
#[derive(Clone, Debug, Display, Deserialize, Serialize)]
1212
#[serde(transparent)]
13-
pub struct User(String);
13+
pub struct User(pub String);
1414

1515
impl<S> OptionalFromRequestParts<S> for User
1616
where

src/state/logger.rs

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,13 @@ impl Logger {
8585
.context(AppendSnafu {
8686
path: self.path.to_path_buf(),
8787
})?;
88+
handle.write(b"\n").await.context(AppendSnafu {
89+
path: self.path.to_path_buf(),
90+
})?;
91+
92+
handle.flush().await.context(IOSnafu {
93+
path: self.path.to_path_buf(),
94+
})?;
8895

8996
Ok(())
9097
}
@@ -114,3 +121,103 @@ impl Logger {
114121
.collect()
115122
}
116123
}
124+
125+
#[cfg(test)]
126+
mod tests {
127+
use async_tempfile::TempFile;
128+
use camino::Utf8PathBuf;
129+
use chrono::Utc;
130+
use tokio::task::JoinSet;
131+
132+
use super::*;
133+
use crate::database::operation::*;
134+
use crate::extractors::user::User;
135+
use crate::routes::category::CategoryForm;
136+
137+
#[tokio::test]
138+
async fn many_writers() {
139+
let mut set = JoinSet::new();
140+
let tmpfile =
141+
Utf8PathBuf::from_path_buf(TempFile::new().await.unwrap().file_path().to_path_buf())
142+
.unwrap();
143+
let logger = Logger::new(tmpfile.clone()).await.unwrap();
144+
145+
let operation_log = OperationLog {
146+
user: Some(User("foo".to_string())),
147+
date: Utc::now(),
148+
table: Table::Category,
149+
operation: OperationType::Create,
150+
operation_id: OperationId {
151+
name: "object".to_string(),
152+
object_id: 1,
153+
},
154+
operation_form: Operation::Category(CategoryForm {
155+
name: "object".to_string(),
156+
path: "path".to_string(),
157+
}),
158+
};
159+
160+
for _i in 0..100 {
161+
let logger = logger.clone();
162+
let operation_log = operation_log.clone();
163+
set.spawn(async move { logger.write(operation_log).await });
164+
}
165+
166+
for task in set.join_all().await {
167+
assert!(task.is_ok());
168+
}
169+
170+
let s = tokio::fs::read_to_string(&tmpfile).await.unwrap();
171+
println!("{s}");
172+
173+
let logs = logger.read().await.unwrap();
174+
assert_eq!(logs.len(), 100);
175+
}
176+
177+
#[tokio::test]
178+
async fn mixed_readers_writers() {
179+
let mut set = JoinSet::new();
180+
let tmpfile =
181+
Utf8PathBuf::from_path_buf(TempFile::new().await.unwrap().file_path().to_path_buf())
182+
.unwrap();
183+
let logger = Logger::new(tmpfile.clone()).await.unwrap();
184+
185+
let operation_log = OperationLog {
186+
user: Some(User("foo".to_string())),
187+
date: Utc::now(),
188+
table: Table::Category,
189+
operation: OperationType::Create,
190+
operation_id: OperationId {
191+
name: "object".to_string(),
192+
object_id: 1,
193+
},
194+
operation_form: Operation::Category(CategoryForm {
195+
name: "object".to_string(),
196+
path: "path".to_string(),
197+
}),
198+
};
199+
200+
for i in 0..200 {
201+
let logger = logger.clone();
202+
if i % 2 == 0 {
203+
let operation_log = operation_log.clone();
204+
set.spawn(async move { logger.write(operation_log).await });
205+
} else {
206+
set.spawn(async move {
207+
let _ = logger.read().await?;
208+
Ok(())
209+
});
210+
}
211+
}
212+
213+
for task in set.join_all().await {
214+
assert!(task.is_ok());
215+
}
216+
217+
let s = tokio::fs::read_to_string(&tmpfile).await.unwrap();
218+
println!("{s}");
219+
220+
let logs = logger.read().await.unwrap();
221+
assert_eq!(logs.len(), 100);
222+
}
223+
}

0 commit comments

Comments
 (0)