revert: replace SQLite tracker with JSON backend (v0.6.0) (#32)

* revert: replace SQLite tracker with JSON backend (v0.6.0)

The SQLite migration (v0.5.0) spawned 21 bug-fix releases in two days:
data-loss risk in the migration layer, schema PK conflicts on per-person
tracking, tracker isolation races under concurrent runs, and a disk-full
error that triggered duplicate Frigate uploads. The complexity cost
outweighs the benefit.

Restored the pre-SQL JSON tracker (frigate_uploaded_ids.json /
frigate_rejected_ids.json in DATA_DIR). Public API is identical — all
callers in executor.py, jobs.py, cli.py, and reconcile.py work unchanged.
Existing JSON files are read automatically; frigate_tracker.db can be
deleted once verified.

* fix: narrow corrupt-thumbnail exception to UnidentifiedImageError; restore IMMICH_URL empty-string fallback

* docs: rewrite v0.6.0 changelog, strip v0.5.x entries, fix README SQLite references

* chore: remove dead get_frigate_filename_for_asset (orphaned since FRIGATE_SCORE_THRESHOLD removal in v0.4.0)

* fix: sort imports in executor.py (ruff I001)
This commit is contained in:
2026-06-15 11:44:41 -04:00
committed by GitHub
parent 0602c4ac04
commit 794dbe2a1d
8 changed files with 346 additions and 766 deletions
+6 -4
View File
@@ -6,6 +6,7 @@ import shutil
from io import BytesIO
from urllib.parse import quote
import PIL
import requests
from PIL import Image
from rich import print as rprint
@@ -162,10 +163,11 @@ def execute_jobs(jobs: list[dict]) -> None:
if resp.ok:
try:
img = Image.open(BytesIO(resp.content))
except Exception:
# resp.ok=True but content is unreadable — corrupt Immich
# thumbnail. Mark rejected so this asset isn't retried
# indefinitely on future runs.
except PIL.UnidentifiedImageError:
# Pillow cannot identify the format — genuinely corrupt
# Immich thumbnail. Mark rejected so this asset isn't
# retried indefinitely. OSError/truncation errors are
# transient and intentionally not caught here.
logger.warning("Invalid image data for asset %s — marking rejected", asset["id"])
mark_rejected(asset["id"], person_name=name)
img = None