'못 찾음'을 유한하게 종료. 두 재시도 축을 분리(기술=큐 attempts/백오프, 검색어=refine 라운드). not_found 는 정상 종료(DONE)지 dead-letter 아님. - ai/keyword: LLM 검색어 생성(정밀/광역) — 원본 0매칭 시에만 지연 호출(비용 절약) - handler: 한정 재정제 루프(원본→정밀→광역, max_rounds=3) + 명시적 outcome(found/not_found) · 0매칭+소스정상 → 다음 라운드, 0매칭+기술실패 → raise(큐 재시도) · 라운드 소진 → not_found + 네거티브 캐시 기록 - negative_cache: search_negative 테이블 + TTL(24h) upsert — 같은 상품 재요청 재검색 차단 - worker_main: OPENAI 있으면 judge+keyword_gen ON, neg_cache 상시 - tests: 재정제/not_found/캐시히트/기술실패/캐시CRUD 11건 → 전체 39/39 - 라이브: 없는상품 3라운드→not_found(30s), 재요청 캐시히트(0.00s) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
37 lines
1.0 KiB
Python
37 lines
1.0 KiB
Python
"""네거티브 캐시 CRUD 테스트 (실 lps_db)."""
|
|
|
|
import pytest_asyncio
|
|
from sqlalchemy import text
|
|
|
|
from crud.negative_cache import NegativeCache
|
|
|
|
|
|
@pytest_asyncio.fixture
|
|
async def nc(db_engine):
|
|
async with db_engine.begin() as conn:
|
|
await conn.execute(text("TRUNCATE search_negative"))
|
|
return NegativeCache()
|
|
|
|
|
|
async def test_put_then_is_negative(nc):
|
|
assert await nc.is_negative("P1") is False
|
|
await nc.put("P1", ttl_sec=3600)
|
|
assert await nc.is_negative("P1") is True
|
|
|
|
|
|
async def test_expired_is_not_negative(nc):
|
|
await nc.put("P2", ttl_sec=-1) # 이미 만료
|
|
assert await nc.is_negative("P2") is False
|
|
|
|
|
|
async def test_upsert_refreshes_ttl(nc):
|
|
await nc.put("P3", ttl_sec=-1) # 만료 상태
|
|
assert await nc.is_negative("P3") is False
|
|
await nc.put("P3", ttl_sec=3600) # 갱신 → 유효
|
|
assert await nc.is_negative("P3") is True
|
|
|
|
|
|
async def test_empty_key_is_noop(nc):
|
|
await nc.put("", ttl_sec=3600)
|
|
assert await nc.is_negative("") is False
|