fix: address four correctness bugs in duplicate detection and tagging

- Duplicate scanner now runs a full-file hash pass (Phase 3) for large
  files (> 64 KB) after the sample-hash shortlist, preventing false
  positives from reaching the destructive deletion workflow
- delete_images_from_disk now attempts filesystem removal before touching
  the DB; only successfully deleted files have their rows removed,
  keeping locked/permission-denied files visible in the library
- AI tag upsert guards user-sourced rows with WHERE source != 'user' so
  a tagger re-run cannot silently overwrite manually added tags
- clear_tagging_jobs excludes 'cancelled' rows from the immediate DELETE
  so the worker can observe cancellation via is_tagging_job_cancelled
  before the rows are cleaned up at next startup
This commit is contained in:
2026-06-06 21:50:53 +01:00
parent c1070649fa
commit f82002129a
2 changed files with 87 additions and 29 deletions
+4 -3
View File
@@ -1697,7 +1697,8 @@ pub fn update_ai_tags(
ON CONFLICT(image_id, tag) DO UPDATE SET
source = 'ai',
ai_model = excluded.ai_model,
confidence = excluded.confidence",
confidence = excluded.confidence
WHERE source != 'user'",
)?;
for (tag, confidence) in tags {
stmt.execute(params![image_id, tag, model, confidence])?;
@@ -1748,7 +1749,7 @@ pub fn clear_tagging_jobs(conn: &Connection, folder_id: Option<i64>) -> Result<u
)?;
let n = conn.execute(
"DELETE FROM tagging_jobs
WHERE status != 'processing'
WHERE status NOT IN ('processing', 'cancelled')
AND image_id IN (SELECT id FROM images WHERE folder_id = ?1)",
[fid],
)?;
@@ -1767,7 +1768,7 @@ pub fn clear_tagging_jobs(conn: &Connection, folder_id: Option<i64>) -> Result<u
WHERE status = 'processing'",
[],
)?;
let n = conn.execute("DELETE FROM tagging_jobs WHERE status != 'processing'", [])?;
let n = conn.execute("DELETE FROM tagging_jobs WHERE status NOT IN ('processing', 'cancelled')", [])?;
conn.execute(
"UPDATE images SET ai_tagger_error = NULL WHERE ai_tagged_at IS NULL",
[],