Fix three bugs found by code audit
- Delete failure retry loop: when delete_frigate_person_files() fails, remove the file from the tracker so the next candidate targets a different worst file rather than re-attempting the same failed delete. - Interactive mode quality replacement: _configure_person() never set config["quality_replacement"], causing the executor to always default to False and silently skip all uploads for at-cap interactive jobs. Now mirrors auto_configure by reading Config.QUALITY_REPLACEMENT. - Silent mapping loss on API flap: after a successful upload, if the post-upload GET /api/faces returns None (transient API failure), the file was silently left unmapped. Now logs a warning so users know quality replacement won't target that file. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+11
-1
@@ -293,6 +293,9 @@ def upload_to_frigate(jobs: list[dict]) -> None:
|
|||||||
known_frigate_files.discard(worst_frigate_file)
|
known_frigate_files.discard(worst_frigate_file)
|
||||||
else:
|
else:
|
||||||
logger.warning(f"Failed to delete {worst_frigate_file} for {name}, skipping replacement")
|
logger.warning(f"Failed to delete {worst_frigate_file} for {name}, skipping replacement")
|
||||||
|
# Remove from tracker so the next candidate targets a different file.
|
||||||
|
# The file stays in Frigate (unmapped, like a manually-added file).
|
||||||
|
remove_frigate_file(name, worst_frigate_file)
|
||||||
progress.advance(upload_task)
|
progress.advance(upload_task)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
@@ -315,7 +318,14 @@ def upload_to_frigate(jobs: list[dict]) -> None:
|
|||||||
|
|
||||||
# Identify the Frigate filename assigned to this upload
|
# Identify the Frigate filename assigned to this upload
|
||||||
# and record the mapping for future quality management.
|
# and record the mapping for future quality management.
|
||||||
current_files = set(get_frigate_person_files(name) or known_frigate_files)
|
fresh = get_frigate_person_files(name)
|
||||||
|
if fresh is None:
|
||||||
|
logger.warning(
|
||||||
|
f"{name}: Frigate API unreachable after uploading {fname}"
|
||||||
|
f" — file mapping skipped, quality replacement won't target this file"
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
current_files = set(fresh)
|
||||||
new_files = current_files - known_frigate_files
|
new_files = current_files - known_frigate_files
|
||||||
if len(new_files) == 1 and asset_id:
|
if len(new_files) == 1 and asset_id:
|
||||||
record_frigate_file(name, next(iter(new_files)), asset_id)
|
record_frigate_file(name, next(iter(new_files)), asset_id)
|
||||||
|
|||||||
+1
-1
@@ -139,7 +139,7 @@ def _configure_person(person: dict, people: list[dict]) -> dict | None:
|
|||||||
mode_choice = Prompt.ask("Choice", choices=["1", "2"], default="1")
|
mode_choice = Prompt.ask("Choice", choices=["1", "2"], default="1")
|
||||||
entity_type = "face" if mode_choice == "1" else "object"
|
entity_type = "face" if mode_choice == "1" else "object"
|
||||||
|
|
||||||
config = {"name": name, "mode": entity_type}
|
config = {"name": name, "mode": entity_type, "quality_replacement": Config.QUALITY_REPLACEMENT}
|
||||||
if entity_type == "object":
|
if entity_type == "object":
|
||||||
config["object_class"] = Prompt.ask("Enter Object Class (e.g. dog, cat, car)", default="dog")
|
config["object_class"] = Prompt.ask("Enter Object Class (e.g. dog, cat, car)", default="dog")
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user