From 63bcd0ffe7dc0530bedf5d3e727862ade58d1e26 Mon Sep 17 00:00:00 2001 From: Diocrafts Date: Sat, 11 Apr 2026 19:13:48 +0200 Subject: [PATCH] perf: non-blocking hash + parallel thumbnail generation - Replace blocking blake3::hash() with DedupService::hash_file() in file_upload_service (create_file, update_file). Uses spawn_blocking + mmap_rayon instead of blocking the Tokio async worker. - Parallelize thumbnail resize+encode with rayon par_iter() for the 3 sizes (Icon, Preview, Large) inside spawn_blocking. --- src/application/services/file_upload_service.rs | 9 +++++++-- src/infrastructure/services/thumbnail_service.rs | 3 ++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/application/services/file_upload_service.rs b/src/application/services/file_upload_service.rs index 6965e9f4..5249789d 100644 --- a/src/application/services/file_upload_service.rs +++ b/src/application/services/file_upload_service.rs @@ -8,6 +8,7 @@ use crate::application::services::storage_usage_service::StorageUsageService; use crate::common::errors::DomainError; use crate::infrastructure::repositories::pg::FileBlobReadRepository; use crate::infrastructure::repositories::pg::FileBlobWriteRepository; +use crate::infrastructure::services::dedup_service::DedupService; use crate::infrastructure::services::file_content_cache::FileContentCache; use tracing::{debug, info, warn}; @@ -211,7 +212,9 @@ impl FileUploadUseCase for FileUploadService { tokio::fs::write(temp.path(), content) .await .map_err(|e| DomainError::internal_error("FileUpload", format!("write temp: {e}")))?; - let hash = blake3::hash(content).to_hex().to_string(); + let hash = DedupService::hash_file(temp.path()) + .await + .map_err(|e| DomainError::internal_error("FileUpload", format!("hash: {e}")))?; let file = self .file_write @@ -246,7 +249,9 @@ impl FileUploadUseCase for FileUploadService { tokio::fs::write(temp.path(), content) .await .map_err(|e| DomainError::internal_error("FileUpload", format!("write temp: {e}")))?; - let hash = blake3::hash(content).to_hex().to_string(); + let hash = DedupService::hash_file(temp.path()) + .await + .map_err(|e| DomainError::internal_error("FileUpload", format!("hash: {e}")))?; self.update_file_streaming( path, diff --git a/src/infrastructure/services/thumbnail_service.rs b/src/infrastructure/services/thumbnail_service.rs index cc66c313..1b38fd7f 100644 --- a/src/infrastructure/services/thumbnail_service.rs +++ b/src/infrastructure/services/thumbnail_service.rs @@ -1,6 +1,7 @@ use bytes::Bytes; use image::codecs::jpeg::JpegEncoder; use image::imageops::FilterType; +use rayon::prelude::*; /** * Thumbnail Generation Service * @@ -534,7 +535,7 @@ impl ThumbnailService { let (orig_w, orig_h) = (img.width(), img.height()); ThumbnailSize::all() - .iter() + .par_iter() .map(|&size| { let max_dim = size.max_dimension();