perf: implement findings #2, #3, #17 from architecture audit

- Finding #2: Replace Mutex<HashMap> with moka::sync::Cache in file_blob_read_repository (10K cap, 30s TTI)
- Finding #3: Add chunked upload persistence with session.json + progress.bin bitmask for crash recovery
- Finding #17: Remove manual gzip compression, delegate entirely to tower-http CompressionLayer
- Remove dead code: StubCompressionPort, GzipCompressionService re-export, duplicate response structs
- All 114 tests passing
This commit is contained in:
Diocrafts
2026-02-22 14:12:53 +01:00
parent 0975f1f7ab
commit fd9e509648
8 changed files with 805 additions and 239 deletions
+6 -13
View File
@@ -7,7 +7,7 @@ use crate::application::services::auth_application_service::AuthApplicationServi
use crate::application::ports::cache_ports::ContentCachePort;
use crate::application::ports::chunked_upload_ports::ChunkedUploadPort;
use crate::application::ports::compression_ports::CompressionPort;
use crate::application::ports::dedup_ports::DedupPort;
use crate::application::ports::favorites_ports::FavoritesUseCase;
use crate::application::ports::file_ports::{
@@ -46,7 +46,7 @@ use crate::infrastructure::services::path_service::PathService;
use crate::infrastructure::services::trash_cleanup_service::TrashCleanupService;
use crate::common::stubs::{
StubCompressionPort, StubDedupPort, StubFileManagementUseCase, StubFileReadPort,
StubDedupPort, StubFileManagementUseCase, StubFileReadPort,
StubFileRetrievalUseCase, StubFileUploadUseCase, StubFileUseCaseFactory, StubFileWritePort,
StubFolderStoragePort, StubFolderUseCase, StubI18nService, StubSearchUseCase, StubZipPort,
};
@@ -124,7 +124,8 @@ impl AppServiceFactory {
let chunked_upload_service = Arc::new(
crate::infrastructure::services::chunked_upload_service::ChunkedUploadService::new(
chunked_temp_dir,
),
)
.await,
);
// Image transcoding service for automatic WebP conversion
@@ -146,13 +147,8 @@ impl AppServiceFactory {
);
dedup_service.initialize().await?;
// Compression service (gzip)
let compression_service: Arc<dyn CompressionPort> = Arc::new(
crate::infrastructure::services::compression_service::GzipCompressionService::new(),
);
tracing::info!(
"Core services initialized: path service, file content cache, thumbnails, chunked upload, image transcode, dedup (PRIMARY blob storage), compression"
"Core services initialized: path service, file content cache, thumbnails, chunked upload, image transcode, dedup (PRIMARY blob storage)"
);
Ok(CoreServices {
@@ -162,7 +158,6 @@ impl AppServiceFactory {
chunked_upload_service,
image_transcode_service,
dedup_service,
compression_service,
zip_service: Arc::new(StubZipPort), // Placeholder - replaced after app services init
config: self.config.clone(),
})
@@ -688,7 +683,6 @@ pub struct CoreServices {
pub chunked_upload_service: Arc<dyn ChunkedUploadPort>,
pub image_transcode_service: Arc<dyn ImageTranscodePort>,
pub dedup_service: Arc<dyn DedupPort>,
pub compression_service: Arc<dyn CompressionPort>,
pub zip_service: Arc<dyn ZipPort>,
pub config: AppConfig,
}
@@ -800,7 +794,7 @@ impl Default for AppState {
// Create dummy chunked upload service
let dummy_chunked_upload_service: Arc<dyn ChunkedUploadPort> = Arc::new(
crate::infrastructure::services::chunked_upload_service::ChunkedUploadService::new(
crate::infrastructure::services::chunked_upload_service::ChunkedUploadService::new_stub(
std::path::PathBuf::from("./storage/.uploads"),
),
);
@@ -825,7 +819,6 @@ impl Default for AppState {
chunked_upload_service: dummy_chunked_upload_service,
image_transcode_service: dummy_image_transcode_service,
dedup_service: dummy_dedup_service,
compression_service: Arc::new(StubCompressionPort) as Arc<dyn CompressionPort>,
zip_service: Arc::new(StubZipPort) as Arc<dyn ZipPort>,
config: config.clone(),
};
-26
View File
@@ -22,7 +22,6 @@ use crate::application::dtos::pagination::{PaginatedResponseDto, PaginationReque
use crate::application::dtos::search_dto::{
SearchCriteriaDto, SearchResultsDto, SearchSuggestionsDto,
};
use crate::application::ports::compression_ports::{CompressionLevel, CompressionPort};
use crate::application::ports::file_ports::{
FileManagementUseCase, FileRetrievalUseCase, FileUploadUseCase, FileUseCaseFactory,
OptimizedFileContent,
@@ -59,31 +58,6 @@ impl ZipPort for StubZipPort {
}
}
// ---------------------------------------------------------------------------
// CompressionPort
// ---------------------------------------------------------------------------
pub struct StubCompressionPort;
#[async_trait]
impl CompressionPort for StubCompressionPort {
async fn compress_data(
&self,
_data: &[u8],
_level: CompressionLevel,
) -> Result<Vec<u8>, DomainError> {
Ok(Vec::new())
}
async fn decompress_data(&self, _compressed_data: &[u8]) -> Result<Vec<u8>, DomainError> {
Ok(Vec::new())
}
fn should_compress(&self, _mime_type: &str, _size: u64) -> bool {
false
}
}
// ---------------------------------------------------------------------------
// FileReadPort
// ---------------------------------------------------------------------------