perf: eliminate Vec<u8> buffer paths — all uploads now stream to disk

Issue #4 (HIGH): save_file(Vec<u8>) and update_file_content(Vec<u8>)
accepted up to 10 MB of contiguous memory per request. While the main
upload paths already used streaming, the WebDAV compat methods
(create_file, update_file) and the empty-file handler still used the
buffered path, creating a .to_vec() copy.

Changes:
- FileWritePort trait: remove save_file(Vec<u8>) and
  update_file_content(Vec<u8>) — only streaming variants remain
- FileUploadUseCase trait: remove upload_file(Vec<u8>)
- file_upload_service.rs: create_file() and update_file() now spool
  &[u8] to NamedTempFile + Sha256::digest, then delegate to streaming
  path (save_file_from_temp / update_file_streaming)
- file_handler.rs: empty file uploads use upload_file_streaming with
- FileBlobWriteRepository: remove save_file and update_file_content impls
- StubFileWritePort, StubFileUploadUseCase, MockFileRepository: remove
  corresponding dead method impls

Impact: impossible to accidentally use a buffered upload path. All
content goes through streaming with ~256 KB peak RAM. -166 LOC.
This commit is contained in:
Dionisio
2026-02-25 23:41:16 +01:00
parent f9dde6ffff
commit 5a1959bf23
7 changed files with 67 additions and 233 deletions
-28
View File
@@ -131,16 +131,6 @@ pub struct StubFileWritePort;
#[async_trait]
impl FileWritePort for StubFileWritePort {
async fn save_file(
&self,
_name: String,
_folder_id: Option<String>,
_content_type: String,
_content: Vec<u8>,
) -> Result<File, DomainError> {
Ok(File::default())
}
async fn save_file_from_temp(
&self,
_name: String,
@@ -177,14 +167,6 @@ impl FileWritePort for StubFileWritePort {
Ok(())
}
async fn update_file_content(
&self,
_file_id: &str,
_content: Vec<u8>,
) -> Result<(), DomainError> {
Ok(())
}
async fn update_file_content_from_temp(
&self,
_file_id: &str,
@@ -454,16 +436,6 @@ impl FileUploadUseCase for StubFileUploadUseCase {
Ok(FileDto::default())
}
async fn upload_file(
&self,
_name: String,
_folder_id: Option<String>,
_content_type: String,
_content: Vec<u8>,
) -> Result<FileDto, DomainError> {
Ok(FileDto::default())
}
async fn upload_file_from_path(
&self,
_name: String,