feat(fc-cleanup): scan_library_for_rule Celery task + maintenance-queue registration — Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,98 @@
|
||||
"""Tests for scan_library_for_rule Celery task.
|
||||
|
||||
Eager mode is used so the task runs synchronously in-test and we can
|
||||
assert state via column selects (post-DML ORM access banned per
|
||||
reference-async-coredml-test-assertions)."""
|
||||
|
||||
import pytest
|
||||
from PIL import Image
|
||||
from sqlalchemy import select
|
||||
|
||||
from backend.app import celery_app
|
||||
from backend.app.models import ImageRecord, LibraryAuditRun
|
||||
|
||||
import backend.app.tasks.library_audit # noqa: F401 — registration
|
||||
|
||||
pytestmark = pytest.mark.integration
|
||||
|
||||
|
||||
def _mk_image(db_sync, tmp_path, *, mode, color, name):
|
||||
path = tmp_path / name
|
||||
Image.new(mode, (10, 10), color).save(path)
|
||||
short_sha = f"fake-{name}"
|
||||
rec = ImageRecord(
|
||||
path=str(path),
|
||||
sha256=short_sha + "0" * (64 - len(short_sha)),
|
||||
size_bytes=path.stat().st_size,
|
||||
mime="image/png",
|
||||
width=10, height=10,
|
||||
origin="imported_filesystem",
|
||||
integrity_status="ok",
|
||||
)
|
||||
db_sync.add(rec)
|
||||
db_sync.flush()
|
||||
return rec, path
|
||||
|
||||
|
||||
def test_scan_library_for_rule_populates_matched_ids_for_transparency(
|
||||
db_sync, tmp_path, monkeypatch,
|
||||
):
|
||||
transparent_rec, _ = _mk_image(
|
||||
db_sync, tmp_path, mode="RGBA", color=(0, 0, 0, 0), name="trans.png",
|
||||
)
|
||||
opaque_rec, _ = _mk_image(
|
||||
db_sync, tmp_path, mode="RGBA", color=(200, 0, 0, 255), name="opaque.png",
|
||||
)
|
||||
audit = LibraryAuditRun(
|
||||
rule="transparency", params={"threshold": 0.5},
|
||||
status="running", matched_ids=[],
|
||||
)
|
||||
db_sync.add(audit)
|
||||
db_sync.commit()
|
||||
audit_id = audit.id
|
||||
|
||||
monkeypatch.setattr(celery_app.celery.conf, "task_always_eager", True)
|
||||
from backend.app.tasks.library_audit import scan_library_for_rule
|
||||
scan_library_for_rule.run(audit_id)
|
||||
monkeypatch.setattr(celery_app.celery.conf, "task_always_eager", False)
|
||||
|
||||
matched = db_sync.execute(
|
||||
select(LibraryAuditRun.matched_ids).where(LibraryAuditRun.id == audit_id)
|
||||
).scalar_one()
|
||||
status = db_sync.execute(
|
||||
select(LibraryAuditRun.status).where(LibraryAuditRun.id == audit_id)
|
||||
).scalar_one()
|
||||
assert transparent_rec.id in matched
|
||||
assert opaque_rec.id not in matched
|
||||
assert status == "ready"
|
||||
|
||||
|
||||
def test_scan_library_for_rule_skips_missing_files_gracefully(
|
||||
db_sync, tmp_path, monkeypatch,
|
||||
):
|
||||
rec, path = _mk_image(
|
||||
db_sync, tmp_path, mode="RGBA", color=(0, 0, 0, 0), name="ghost.png",
|
||||
)
|
||||
path.unlink() # delete the file but leave the DB row
|
||||
audit = LibraryAuditRun(
|
||||
rule="transparency", params={"threshold": 0.5},
|
||||
status="running", matched_ids=[],
|
||||
)
|
||||
db_sync.add(audit)
|
||||
db_sync.commit()
|
||||
audit_id = audit.id
|
||||
|
||||
monkeypatch.setattr(celery_app.celery.conf, "task_always_eager", True)
|
||||
from backend.app.tasks.library_audit import scan_library_for_rule
|
||||
scan_library_for_rule.run(audit_id)
|
||||
monkeypatch.setattr(celery_app.celery.conf, "task_always_eager", False)
|
||||
|
||||
status = db_sync.execute(
|
||||
select(LibraryAuditRun.status).where(LibraryAuditRun.id == audit_id)
|
||||
).scalar_one()
|
||||
matched = db_sync.execute(
|
||||
select(LibraryAuditRun.matched_ids).where(LibraryAuditRun.id == audit_id)
|
||||
).scalar_one()
|
||||
# Missing file is skipped (warning logged), audit completes successfully.
|
||||
assert status == "ready"
|
||||
assert rec.id not in matched
|
||||
Reference in New Issue
Block a user