feat: run matcher after successful scrape; failures don't flip scrape status

This commit is contained in:
2026-05-06 06:21:54 -07:00
parent 6dfb84310f
commit db4b01337e
2 changed files with 85 additions and 0 deletions
+6
View File
@@ -86,6 +86,12 @@ def _run_scrape_in_background(
log.duration_seconds = int( log.duration_seconds = int(
(log.completed_at - log.started_at).total_seconds() (log.completed_at - log.started_at).total_seconds()
) )
try:
from app.services.matcher import run_match_job
run_match_job(db, source_filter="lucky_california")
except Exception as e: # matcher failure must not flip scrape to FAILED
import logging
logging.exception("matcher failed after successful scrape: %s", e)
db.commit() db.commit()
logger.info( logger.info(
"Background scrape %s complete: %s/%s items saved", "Background scrape %s complete: %s/%s items saved",
+79
View File
@@ -0,0 +1,79 @@
import pytest
pytestmark = pytest.mark.requires_postgres
def test_run_match_job_persists_top_matches(monkeypatch):
"""End-to-end: seed Ingredient + GroceryItem rows, run the matcher,
verify ingredient_grocery_match rows exist with confidence >= 0.75.
"""
from datetime import datetime, timezone
from decimal import Decimal
from uuid import uuid4
from app.database import SessionLocal
from app.models import (
GroceryItem,
Ingredient,
IngredientGroceryMatch,
IngredientMatchSource,
)
from app.services.matcher import run_match_job
setup = SessionLocal()
ing_id = uuid4()
grocery_id = uuid4()
try:
setup.add(
Ingredient(
id=ing_id,
name="Zorblax Fizzberry Test",
name_lower="zorblax fizzberry test",
aliases=["zorblax fizzberry"],
aisle="meat",
unit="lb",
)
)
setup.add(
GroceryItem(
id=grocery_id,
name="Zorblax Fizzberry Family Pack",
source="lucky_california",
external_id="ext-test-1",
current_price=Decimal("3.99"),
regular_price=Decimal("5.49"),
is_on_sale=True,
scraped_at=datetime.now(timezone.utc),
)
)
setup.commit()
finally:
setup.close()
work = SessionLocal()
try:
written = run_match_job(work)
assert written >= 1
rows = (
work.query(IngredientGroceryMatch)
.filter(IngredientGroceryMatch.ingredient_id == ing_id)
.all()
)
assert any(
r.grocery_item_id == grocery_id
and r.confidence >= Decimal("0.750")
and r.source == IngredientMatchSource.AUTO
for r in rows
)
finally:
cleanup = SessionLocal()
try:
cleanup.query(IngredientGroceryMatch).filter(
IngredientGroceryMatch.ingredient_id == ing_id
).delete()
cleanup.query(GroceryItem).filter(GroceryItem.id == grocery_id).delete()
cleanup.query(Ingredient).filter(Ingredient.id == ing_id).delete()
cleanup.commit()
finally:
cleanup.close()
work.close()