11use camino:: Utf8PathBuf ;
22use snafu:: prelude:: * ;
33use tokio:: fs:: { File , OpenOptions } ;
4+ use tokio:: io:: AsyncWriteExt ;
45use tokio:: sync:: RwLock ;
56
67use std:: sync:: Arc ;
78
9+ use crate :: database:: operation:: Operation ;
10+
811#[ derive( Debug , Snafu ) ]
912#[ snafu( visibility( pub ) ) ]
1013pub enum LoggerError {
1114 /// Failed to create the log file, which did not previously exist.
1215 #[ snafu( display( "Failed to create the operations log {path}" ) ) ]
13- Create { path : Utf8PathBuf , source : std:: io:: Error } ,
16+ Create {
17+ path : Utf8PathBuf ,
18+ source : std:: io:: Error ,
19+ } ,
1420 /// Failed to read the log file
1521 #[ snafu( display( "Failed to read the operations log {path}" ) ) ]
16- Read { path : Utf8PathBuf , source : std:: io:: Error } ,
22+ Read {
23+ path : Utf8PathBuf ,
24+ source : std:: io:: Error ,
25+ } ,
1726 /// Failed to append a line to the log file
1827 #[ snafu( display( "Failed to append to the operations log {path}" ) ) ]
19- Append { path : Utf8PathBuf , source : std:: io:: Error } ,
28+ Append {
29+ path : Utf8PathBuf ,
30+ source : std:: io:: Error ,
31+ } ,
2032 #[ snafu( display( "Failed to parse JSON from operations log {path}" ) ) ]
21- Parse { path : Utf8PathBuf , source : serde_json:: Error } ,
33+ Parse {
34+ path : Utf8PathBuf ,
35+ source : serde_json:: Error ,
36+ } ,
2237}
2338
2439#[ derive( Clone , Debug ) ]
2540pub struct Logger {
2641 /// Log file storage
2742 pub path : Utf8PathBuf ,
28-
43+
2944 /// Handle to the log file in append-mode
3045 pub handle : Arc < RwLock < File > > ,
3146}
@@ -34,16 +49,37 @@ impl Logger {
3449 pub async fn new ( path : Utf8PathBuf ) -> Result < Self , LoggerError > {
3550 let mut handle = OpenOptions :: new ( ) ;
3651 let mut handle = handle. append ( true ) . read ( true ) ;
37- let handle = if !tokio:: fs:: try_exists ( & path) . await . context ( ReadSnafu { path : path. to_path_buf ( ) } ) ? {
52+ let handle = if !tokio:: fs:: try_exists ( & path) . await . context ( ReadSnafu {
53+ path : path. to_path_buf ( ) ,
54+ } ) ? {
3855 handle = handle. create ( true ) ;
39- handle. open ( & path) . await . context ( CreateSnafu { path : path. to_path_buf ( ) } ) ?
56+ handle. open ( & path) . await . context ( CreateSnafu {
57+ path : path. to_path_buf ( ) ,
58+ } ) ?
4059 } else {
41- handle. open ( & path) . await . context ( ReadSnafu { path : path. to_path_buf ( ) } ) ?
60+ handle. open ( & path) . await . context ( ReadSnafu {
61+ path : path. to_path_buf ( ) ,
62+ } ) ?
4263 } ;
4364
4465 Ok ( Self {
4566 path : path. to_path_buf ( ) ,
4667 handle : Arc :: new ( RwLock :: new ( handle) ) ,
4768 } )
4869 }
70+
71+ pub async fn write ( & self , operation : Operation ) -> Result < ( ) , LoggerError > {
72+ // This should never fail
73+ let operation = serde_json:: to_string ( & operation) . unwrap ( ) ;
74+
75+ let mut handle = self . handle . write ( ) . await ;
76+ handle
77+ . write ( operation. as_bytes ( ) )
78+ . await
79+ . context ( AppendSnafu {
80+ path : self . path . to_path_buf ( ) ,
81+ } ) ?;
82+
83+ Ok ( ( ) )
84+ }
4985}
0 commit comments