From 2f61d7e9fac03f462029e7a771579d893453162e Mon Sep 17 00:00:00 2001 From: NotAShelf Date: Mon, 9 Feb 2026 17:11:43 +0300 Subject: [PATCH] pinakes-server: add chunked upload manager to app state with periodic cleanup Signed-off-by: NotAShelf Change-Id: I3462c21ff359b4e3a7eca9a82abd50086a6a6964 --- crates/pinakes-server/src/main.rs | 56 +++++++++++++++++++++++++++++- crates/pinakes-server/src/state.rs | 2 ++ 2 files changed, 57 insertions(+), 1 deletion(-) diff --git a/crates/pinakes-server/src/main.rs b/crates/pinakes-server/src/main.rs index e0ba14b..d513fcd 100644 --- a/crates/pinakes-server/src/main.rs +++ b/crates/pinakes-server/src/main.rs @@ -523,6 +523,32 @@ async fn main() -> Result<()> { } }; + // Initialize chunked upload manager if sync is enabled + let chunked_upload_manager = { + let config_read = config_arc.read().await; + if config_read.sync.enabled { + let manager = pinakes_core::sync::ChunkedUploadManager::new( + config_read.sync.temp_upload_dir.clone(), + ); + match manager.init().await { + Ok(()) => { + info!( + path = %config_read.sync.temp_upload_dir.display(), + "chunked upload manager initialized" + ); + Some(Arc::new(manager)) + } + Err(e) => { + tracing::error!(error = %e, "failed to initialize chunked upload manager"); + None + } + } + } else { + tracing::info!("sync disabled, chunked upload manager not initialized"); + None + } + }; + let state = AppState { storage: storage.clone(), config: config_arc.clone(), @@ -534,6 +560,7 @@ async fn main() -> Result<()> { plugin_manager, transcode_service, managed_storage, + chunked_upload_manager, }; // Periodic session cleanup (every 15 minutes) @@ -549,10 +576,37 @@ async fn main() -> Result<()> { Ok(count) if count > 0 => { tracing::info!(count = count, "cleaned up expired sessions"); } - Ok(_) => {} // No sessions to clean up Err(e) => { tracing::error!(error = %e, "failed to cleanup expired sessions"); } + _ => {} + } + } + _ = cancel.cancelled() => { + break; + } + } + } + }); + } + + // Periodic chunked upload cleanup (every hour) + if let Some(ref manager) = state.chunked_upload_manager { + let manager_clone = manager.clone(); + let cancel = shutdown_token.clone(); + tokio::spawn(async move { + let mut interval = tokio::time::interval(std::time::Duration::from_secs(60 * 60)); + loop { + tokio::select! { + _ = interval.tick() => { + match manager_clone.cleanup_expired(48).await { + Ok(count) if count > 0 => { + tracing::info!(count = count, "cleaned up expired upload temp files"); + } + Err(e) => { + tracing::error!(error = %e, "failed to cleanup expired upload temp files"); + } + _ => {} } } _ = cancel.cancelled() => { diff --git a/crates/pinakes-server/src/state.rs b/crates/pinakes-server/src/state.rs index 6d61f04..3bf99bf 100644 --- a/crates/pinakes-server/src/state.rs +++ b/crates/pinakes-server/src/state.rs @@ -11,6 +11,7 @@ use pinakes_core::plugin::PluginManager; use pinakes_core::scan::ScanProgress; use pinakes_core::scheduler::TaskScheduler; use pinakes_core::storage::DynStorageBackend; +use pinakes_core::sync::ChunkedUploadManager; use pinakes_core::transcode::TranscodeService; // Note: Sessions are now stored in the database via StorageBackend @@ -28,4 +29,5 @@ pub struct AppState { pub plugin_manager: Option>, pub transcode_service: Option>, pub managed_storage: Option>, + pub chunked_upload_manager: Option>, }