@@ -4,6 +4,7 @@ use std::{
44 net:: { IpAddr , SocketAddr } ,
55 path:: PathBuf ,
66 sync:: LazyLock ,
7+ time:: { Duration , SystemTime , UNIX_EPOCH } ,
78} ;
89
910use axum:: {
@@ -23,9 +24,10 @@ use tokio::{
2324 net:: TcpListener ,
2425 runtime:: Runtime ,
2526 task:: spawn_blocking,
27+ time:: interval,
2628} ;
2729use tower_http:: trace:: { self , TraceLayer } ;
28- use tracing:: { Level , info} ;
30+ use tracing:: { Level , info, warn } ;
2931
3032use meme_generator:: {
3133 MEME_HOME , VERSION ,
@@ -58,6 +60,42 @@ fn clear_temp_dir() {
5860 let _ = std:: fs:: create_dir ( & * TEMP_DIR ) ;
5961}
6062
63+ async fn cleanup_temp_files ( ) {
64+ let temp_dir = & * TEMP_DIR ;
65+ if !temp_dir. exists ( ) {
66+ return ;
67+ }
68+
69+ let now = SystemTime :: now ( )
70+ . duration_since ( UNIX_EPOCH )
71+ . unwrap ( )
72+ . as_secs ( ) ;
73+ let max_age_seconds = 10 * 60 ;
74+ let mut deleted_count = 0 ;
75+
76+ if let Ok ( entries) = std:: fs:: read_dir ( temp_dir) {
77+ for entry in entries {
78+ if let Ok ( entry) = entry
79+ && let Ok ( metadata) = entry. metadata ( )
80+ && metadata. is_file ( )
81+ && let Ok ( modified) = metadata. modified ( )
82+ && let Ok ( modified_secs) = modified. duration_since ( UNIX_EPOCH )
83+ && now - modified_secs. as_secs ( ) > max_age_seconds
84+ {
85+ if let Err ( e) = std:: fs:: remove_file ( entry. path ( ) ) {
86+ warn ! ( "Failed to delete temp file {:?}: {}" , entry. path( ) , e) ;
87+ } else {
88+ deleted_count += 1 ;
89+ }
90+ }
91+ }
92+ }
93+
94+ if deleted_count > 0 {
95+ info ! ( "Cleaned up {} temporary files" , deleted_count) ;
96+ }
97+ }
98+
6199#[ derive( Debug ) ]
62100pub ( crate ) enum ServerError {
63101 RequestError ( reqwest:: Error ) ,
@@ -382,6 +420,17 @@ pub(crate) fn handle_error(error: Error) -> ErrorResponse {
382420
383421pub async fn run_server ( host : Option < IpAddr > , port : Option < u16 > ) {
384422 clear_temp_dir ( ) ;
423+
424+ let cleanup_task = {
425+ let mut interval = interval ( Duration :: from_secs ( 10 * 60 ) ) ;
426+ tokio:: spawn ( async move {
427+ loop {
428+ interval. tick ( ) . await ;
429+ cleanup_temp_files ( ) . await ;
430+ }
431+ } )
432+ } ;
433+
385434 let app = Router :: new ( )
386435 . route ( "/image/upload" , post ( upload_image) )
387436 . layer ( DefaultBodyLimit :: disable ( ) )
@@ -434,7 +483,13 @@ pub async fn run_server(host: Option<IpAddr>, port: Option<u16>) {
434483 let addr = SocketAddr :: new ( host, port) ;
435484 let listener = TcpListener :: bind ( addr) . await . unwrap ( ) ;
436485 info ! ( "Server running on {}" , addr) ;
437- axum:: serve ( listener, app) . await . unwrap ( ) ;
486+
487+ tokio:: select! {
488+ _ = axum:: serve( listener, app) => {
489+ info!( "Server stopped" ) ;
490+ }
491+ _ = cleanup_task => { }
492+ }
438493}
439494
440495pub fn run_server_sync ( host : Option < IpAddr > , port : Option < u16 > ) {
0 commit comments