bugfix/thumbnails on update

Bug 1 & 2 (webdav_handler.rs handle_put() update branch):
  - After a successful file update via WebDAV PUT, if the content type is a supported image:
    a. delete_thumbnails(file_id) — evicts the stale moka cache entry
    b. Spawns a background task to read the new blob bytes and call generate_all_sizes_background_from_bytes

  Bug 3 & 4 (dedup_service.rs):
  - Added thumbnail_service: Option<Arc<ThumbnailService>> field with a with_thumbnail_service() builder
  - In remove_legacy_reference(): calls delete_blob_thumbnails(hash) when ref_count hits 0
  - In remove_manifest_reference(): calls delete_blob_thumbnails(file_hash) when manifest's last ref is dropped
  - Wired in di.rs — the thumbnail service is created before dedup service so the ordering works cleanly
This commit is contained in:
Edouard Vanbelle
2026-04-27 20:41:19 +02:00
parent f62562d585
commit 9f57776ec9
6 changed files with 105 additions and 2 deletions
+44 -1
View File
@@ -263,7 +263,8 @@ impl AppServiceFactory {
blob_backend,
db_pool.clone(),
maintenance_pool.clone(),
),
)
.with_thumbnail_service(thumbnail_service.clone()),
);
dedup_service.initialize().await?;
@@ -981,6 +982,48 @@ pub struct CoreServices {
pub config: AppConfig,
}
impl CoreServices {
/// Invalidate a file's moka thumbnail cache and kick off background regeneration.
///
/// Call this after any write that swaps the blob for an existing file.
/// Safe to call for new files too (no-op on empty cache).
/// Skips everything if the MIME type is not a supported image.
pub async fn refresh_thumbnails_after_update(
&self,
file_id: String,
blob_hash: String,
content_type: &str,
) {
if !ThumbnailService::is_supported_image(content_type) {
return;
}
if let Err(e) = self.thumbnail_service.delete_thumbnails(&file_id).await {
tracing::warn!(
"Failed to invalidate thumbnail cache for {}: {}",
file_id,
e
);
}
let ts = self.thumbnail_service.clone();
let ds = self.dedup_service.clone();
let hash = blob_hash.clone();
tokio::spawn(async move {
match ds.read_blob_bytes(&hash).await {
Ok(bytes) => {
ts.generate_all_sizes_background_from_bytes(file_id, hash, bytes);
}
Err(e) => {
tracing::warn!(
"Failed to read blob for thumbnail regeneration {}: {}",
file_id,
e
);
}
}
});
}
}
/// Container for repository services
#[derive(Clone)]
pub struct RepositoryServices {