perf: URL→Byte-Hash-Erinnerung — bekannte Bilder nicht erneut laden/analysieren
Bisher: Die Analyse identischer Bilder war bereits dedupliziert (Ledger nach Byte-Hash indiziert). Aber jede Bild-URL wurde bei jedem Scan ERNEUT heruntergeladen, um ihren Hash für Gruppierung/Abdeckung zu berechnen — auch wenn die Bytes längst bekannt und analysiert waren. Neu: persistente URL→Hash-Map im Ledger (url_hashes). Eine bereits gesehene Bild-URL wird nicht erneut geladen; Abdeckung umfasst nur noch nie gesehene URLs. Duplikate (gleiche Bytes an mehreren URLs) werden je URL höchstens einmal geholt und nie doppelt analysiert. Geänderte/geflaggte Bilder werden weiterhin IMMER (erneut) geprüft. Spart Bandbreite/Zeit und schont den überwachten Server (Fetch nur für Neues). Byte-Änderungen bereits bekannter Bilder auf stabilen Seiten deckt weiterhin check-assets ab (Integritäts-Layer). Tests: 258 grün (+1: Duplikat-URLs einmal geladen, einmal analysiert, danach kein erneuter Fetch). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
369a3b8774
commit
4db5817013
2 changed files with 48 additions and 15 deletions
|
|
@ -230,6 +230,32 @@ class TestImages:
|
|||
if e.get("kind") == "image"}
|
||||
assert len(analysed) == 5 # nach 3 Scans sind alle 5 Bilder abgedeckt
|
||||
|
||||
def test_duplicate_image_urls_fetched_once_analyzed_once(self, tmp_path, monkeypatch):
|
||||
"""Gleiches Bild an mehreren URLs: nur EINE Analyse; danach kein erneuter Fetch
|
||||
(Byte-Hash gemerkt und geprüft)."""
|
||||
monkeypatch.setenv("OPENROUTER_API_KEY", "test")
|
||||
bm = BaselineManager(tmp_path)
|
||||
cfg = self._cfg_img()
|
||||
imgs = [{"url": "https://x.de/a.jpg", "class": "internal"},
|
||||
{"url": "https://x.de/b.jpg", "class": "internal"}]
|
||||
snap = _snap("kurz", img=imgs)
|
||||
same = {"https://x.de/a.jpg": {"sha256": "DUP", "size": 1, "error": None},
|
||||
"https://x.de/b.jpg": {"sha256": "DUP", "size": 1, "error": None}}
|
||||
with patch("scanner.ai_analyzer.fetch_asset_hashes", return_value=same), \
|
||||
patch("scanner.ai_analyzer._openrouter_chat", return_value=_verdict()):
|
||||
res1 = run_ai_analysis(cfg, bm, snap, {})
|
||||
assert res1["api_calls"] == 1 # gleiche Bytes → nur EINE Analyse
|
||||
led = bm.load_ai_ledger()
|
||||
assert set(led["url_hashes"]) == {"https://x.de/a.jpg", "https://x.de/b.jpg"}
|
||||
|
||||
# zweiter Scan: beide URLs bekannt → gar kein Fetch, keine Analyse mehr
|
||||
with patch("scanner.ai_analyzer.fetch_asset_hashes") as fetch2, \
|
||||
patch("scanner.ai_analyzer._openrouter_chat") as chat2:
|
||||
res2 = run_ai_analysis(cfg, bm, snap, {})
|
||||
fetch2.assert_not_called()
|
||||
chat2.assert_not_called()
|
||||
assert res2["api_calls"] == 0
|
||||
|
||||
def test_image_backlog_unlimited_covers_all_in_one_scan(self, tmp_path, monkeypatch):
|
||||
"""max_images_per_scan=0 → voller Bildbestand in EINEM Scan (Default)."""
|
||||
monkeypatch.setenv("OPENROUTER_API_KEY", "test")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue