fix(naver-fetch): realestate base :18800 + 동별 ingest + 180s no-retry

This commit is contained in:
2026-07-10 10:55:51 +09:00
parent 0b4e4c2e0e
commit 8e64c4feb8
8 changed files with 56 additions and 47 deletions

View File

@@ -23,14 +23,15 @@ def test_in_daytime_boundaries():
class _FakeNAS:
def __init__(self, targets):
self._targets = targets
self.ingested = None
self.ingests = [] # 동별 post_ingest 호출 기록
async def get_targets(self):
return self._targets
async def post_ingest(self, fetched_at, batches):
self.ingested = {"fetched_at": fetched_at, "batches": batches}
return {"received": sum(len(b["articles"]) for b in batches), "new": 1, "matched": 1}
self.ingests.append({"fetched_at": fetched_at, "batches": batches})
n = sum(len(b["articles"]) for b in batches)
return {"received": n, "new": n, "matched": 0}
class _FakeNaver:
@@ -48,7 +49,7 @@ class _FakeNaver:
"articleList": [{"articleNo": f"{cortar_no}-{page}"}]}
async def test_run_cycle_assembles_batches_and_ingests():
async def test_run_cycle_ingests_per_dong():
nas = _FakeNAS({"dongs": [{"dong": "신대방동", "cortar_no": "1159010100"},
{"dong": "봉천동", "cortar_no": "1162010100"}],
"deal_types": ["매매"], "page_limit": 1})
@@ -56,13 +57,14 @@ async def test_run_cycle_assembles_batches_and_ingests():
state = FetchState()
await run_cycle(nas, naver, state, load_settings())
assert naver.token_acquired is True
assert nas.ingested is not None
dongs = [b["dong"] for b in nas.ingested["batches"]]
assert len(nas.ingests) == 2 # 동별 1 POST씩
dongs = [ing["batches"][0]["dong"] for ing in nas.ingests]
assert dongs == ["신대방동", "봉천동"]
assert all(len(ing["batches"]) == 1 for ing in nas.ingests)
assert state.listings_pushed == 2
assert state.last_fetch_at is not None
assert state.state == "idle"
assert nas.ingested["fetched_at"].endswith("Z")
assert nas.ingests[0]["fetched_at"].endswith("Z")
async def test_run_cycle_dong_failure_isolated():
@@ -72,11 +74,10 @@ async def test_run_cycle_dong_failure_isolated():
naver = _FakeNaver(fail_dongs={"1159010100"})
state = FetchState()
await run_cycle(nas, naver, state, load_settings())
assert nas.ingested is not None # 실패해도 ingest 진행
# A는 fetch 실패 → ingest skip, B만 ingest (부분 실패 격리)
assert len(nas.ingests) == 1
assert nas.ingests[0]["batches"][0]["dong"] == "B"
assert state.errors >= 1
batches = {b["dong"]: b["articles"] for b in nas.ingested["batches"]}
assert batches["A"] == [] # 실패 동 빈 배열
assert len(batches["B"]) == 1 # 성공 동
async def test_run_cycle_token_failure_skips_ingest():
@@ -87,7 +88,7 @@ async def test_run_cycle_token_failure_skips_ingest():
nas = _FakeNAS({"dongs": [], "page_limit": 1})
state = FetchState()
await run_cycle(nas, _BadNaver(), state, load_settings())
assert nas.ingested is None
assert nas.ingests == []
assert state.errors == 1
assert state.state == "idle"