release: v0.5.13 — robustness fixes from full-project audit

- executor.py: wrap shutil.rmtree/os.makedirs in try/except OSError so a
  permission failure logs and skips the job rather than aborting the run
- cache.py: write embeddings to a .tmp file and atomically rename into place
  via os.replace so a process kill can't leave a corrupted .npy cache slot
- immich_api.py: guard fileCreatedAt with isinstance(str) check before calling
  .replace() so a non-string timestamp doesn't raise AttributeError and kill
  the entire filter_recent_assets pass
- upload_tracker.py: raise SQLite busy timeout from 5 s to 30 s to handle
  concurrent cron+manual run overlap without dropping upload-tracking records
This commit is contained in:
2026-06-15 01:19:38 +00:00
parent 850ae2f9fc
commit 51f7ed3961
6 changed files with 31 additions and 7 deletions
+8 -3
View File
@@ -114,9 +114,14 @@ def execute_jobs(jobs: list[dict]) -> None:
logger.error("person_dir %s became a symlink after path check — skipping job", person_dir)
progress.remove_task(job_task)
continue
if os.path.isdir(person_dir):
shutil.rmtree(person_dir)
os.makedirs(person_dir, exist_ok=True)
try:
if os.path.isdir(person_dir):
shutil.rmtree(person_dir)
os.makedirs(person_dir, exist_ok=True)
except OSError as e:
logger.error("Failed to prepare output dir for %s: %s", name, e)
progress.remove_task(job_task)
continue
# Track filename → asset_id, filename → confidence score, filename → crop dims
asset_map: dict[str, str] = {}