@@ -15,16 +15,20 @@ fn runs_dir() -> PathBuf {
1515}
1616
1717/// Ensure the necessary directories exist for storing data.
18- pub fn ensure_dirs ( ) -> Result < ( ) > {
19- std:: fs:: create_dir_all ( runs_dir ( ) ) . context ( "create runs dir" ) ?;
18+ pub async fn ensure_dirs ( ) -> Result < ( ) > {
19+ tokio:: fs:: create_dir_all ( runs_dir ( ) )
20+ . await
21+ . context ( "create runs dir" ) ?;
2022 Ok ( ( ) )
2123}
2224
23- pub fn save_run ( result : & RunResult ) -> Result < PathBuf > {
24- ensure_dirs ( ) ?;
25+ pub async fn save_run ( result : & RunResult ) -> Result < PathBuf > {
26+ ensure_dirs ( ) . await ?;
2527 let path = get_run_path ( result) ?;
2628 let data = serde_json:: to_vec_pretty ( result) ?;
27- std:: fs:: write ( & path, data) . context ( "write run json" ) ?;
29+ tokio:: fs:: write ( & path, data)
30+ . await
31+ . context ( "write run json" ) ?;
2832 Ok ( path)
2933}
3034
@@ -34,28 +38,36 @@ pub fn get_run_path(result: &RunResult) -> Result<PathBuf> {
3438 Ok ( runs_dir ( ) . join ( format ! ( "run-{safe_ts}-{}.json" , result. meas_id) ) )
3539}
3640
37- pub fn delete_run ( result : & RunResult ) -> Result < ( ) > {
41+ pub async fn delete_run ( result : & RunResult ) -> Result < ( ) > {
3842 let path = get_run_path ( result) ?;
39- if path. exists ( ) {
40- std:: fs:: remove_file ( & path) . context ( "delete run file" ) ?;
43+ if tokio:: fs:: try_exists ( & path) . await . unwrap_or ( false ) {
44+ tokio:: fs:: remove_file ( & path)
45+ . await
46+ . context ( "delete run file" ) ?;
4147 }
4248 Ok ( ( ) )
4349}
4450
45- pub fn export_json ( path : & Path , result : & RunResult ) -> Result < ( ) > {
51+ pub async fn export_json ( path : & Path , result : & RunResult ) -> Result < ( ) > {
4652 // Create parent directories if they don't exist
4753 if let Some ( parent) = path. parent ( ) {
48- std:: fs:: create_dir_all ( parent) . context ( "create export directory" ) ?;
54+ tokio:: fs:: create_dir_all ( parent)
55+ . await
56+ . context ( "create export directory" ) ?;
4957 }
5058 let data = serde_json:: to_vec_pretty ( result) ?;
51- std:: fs:: write ( path, data) . context ( "write export json" ) ?;
59+ tokio:: fs:: write ( path, data)
60+ . await
61+ . context ( "write export json" ) ?;
5262 Ok ( ( ) )
5363}
5464
55- pub fn export_csv ( path : & Path , result : & RunResult ) -> Result < ( ) > {
65+ pub async fn export_csv ( path : & Path , result : & RunResult ) -> Result < ( ) > {
5666 // Create parent directories if they don't exist
5767 if let Some ( parent) = path. parent ( ) {
58- std:: fs:: create_dir_all ( parent) . context ( "create export directory" ) ?;
68+ tokio:: fs:: create_dir_all ( parent)
69+ . await
70+ . context ( "create export directory" ) ?;
5971 }
6072 let mut out = String :: new ( ) ;
6173 out. push_str ( "timestamp_utc,base_url,meas_id,comments,server,download_mbps,upload_mbps,idle_mean_ms,idle_median_ms,idle_p25_ms,idle_p75_ms,idle_loss,dl_loaded_mean_ms,dl_loaded_median_ms,dl_loaded_p25_ms,dl_loaded_p75_ms,dl_loaded_loss,ul_loaded_mean_ms,ul_loaded_median_ms,ul_loaded_p25_ms,ul_loaded_p75_ms,ul_loaded_loss,ip,colo,asn,as_org,interface_name,network_name,is_wireless,interface_mac,link_speed_mbps\n " ) ;
@@ -93,7 +105,9 @@ pub fn export_csv(path: &Path, result: &RunResult) -> Result<()> {
93105 csv_escape( result. interface_mac. as_deref( ) . unwrap_or( "" ) ) ,
94106 result. link_speed_mbps. map( |s| s. to_string( ) ) . unwrap_or_else( || "" . to_string( ) ) ,
95107 ) ) ;
96- std:: fs:: write ( path, out) . context ( "write export csv" ) ?;
108+ tokio:: fs:: write ( path, out)
109+ . await
110+ . context ( "write export csv" ) ?;
97111 Ok ( ( ) )
98112}
99113
@@ -106,17 +120,17 @@ fn csv_escape(s: &str) -> String {
106120 }
107121}
108122
109- pub fn load_recent ( limit : usize ) -> Result < Vec < RunResult > > {
110- ensure_dirs ( ) ?;
123+ pub async fn load_recent ( limit : usize ) -> Result < Vec < RunResult > > {
124+ ensure_dirs ( ) . await ?;
111125 let dir = runs_dir ( ) ;
112126 let mut entries: Vec < ( std:: time:: SystemTime , PathBuf ) > = Vec :: new ( ) ;
113- for e in std :: fs:: read_dir ( & dir) . context ( "read runs dir" ) ? {
114- let e = e? ;
127+ let mut dir_iter = tokio :: fs:: read_dir ( & dir) . await . context ( "read runs dir" ) ?;
128+ while let Some ( e ) = dir_iter . next_entry ( ) . await ? {
115129 let p = e. path ( ) ;
116130 if p. extension ( ) . and_then ( |e| e. to_str ( ) ) != Some ( "json" ) {
117131 continue ;
118132 }
119- let m = e. metadata ( ) ?;
133+ let m = e. metadata ( ) . await ?;
120134 let mt = m. modified ( ) . unwrap_or ( std:: time:: SystemTime :: UNIX_EPOCH ) ;
121135 entries. push ( ( mt, p) ) ;
122136 }
@@ -125,7 +139,9 @@ pub fn load_recent(limit: usize) -> Result<Vec<RunResult>> {
125139
126140 let mut out = Vec :: new ( ) ;
127141 for ( _, p) in entries. into_iter ( ) . take ( limit) {
128- let data = std:: fs:: read ( & p) . with_context ( || format ! ( "read {}" , p. display( ) ) ) ?;
142+ let data = tokio:: fs:: read ( & p)
143+ . await
144+ . with_context ( || format ! ( "read {}" , p. display( ) ) ) ?;
129145 let r: RunResult =
130146 serde_json:: from_slice ( & data) . with_context ( || format ! ( "parse {}" , p. display( ) ) ) ?;
131147 out. push ( r) ;
0 commit comments