From 2e19dc3d37dbcefacb9af8bd2bcecf1247585dee Mon Sep 17 00:00:00 2001 From: hyungi Date: Tue, 16 Jun 2026 13:32:07 +0900 Subject: [PATCH] =?UTF-8?q?fix(collectors):=20kosha=20=EB=B6=80=EB=B6=84?= =?UTF-8?q?=EC=8B=A4=ED=8C=A8=20per-case=20commit=20=E2=80=94=20=EC=A0=84?= =?UTF-8?q?=EC=B2=B4=20rollback=20=EB=B0=A9=EC=A7=80=20(R4)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit kosha run() 이 소스별 단일 세션으로 collector 전체를 돌리고 예외 시 rollback → 페이지 _api_get 실패가 앞서 적재한 케이스/항목을 전부 폐기(부분 적재 손실 + 매번 같은 지점 실패 시 영구 미적재). disaster_cases/fatal_accidents/guide 의 케이스·항목 단위로 session.commit() 경계 추가(csb/api_standards idiom) — 실패 이전 적재분 보존, dedup 으로 다음 run 이 이어받음. 첨부 실패는 기존대로 격리(변경 없음). 검증: py_compile 통과. Co-Authored-By: Claude Opus 4.8 (1M context) --- app/workers/kosha_collector.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/app/workers/kosha_collector.py b/app/workers/kosha_collector.py index 0ece796..0d873c3 100644 --- a/app/workers/kosha_collector.py +++ b/app/workers/kosha_collector.py @@ -297,6 +297,10 @@ async def collect_disaster_cases(session) -> int: await _ingest_attachment(session, boardno, filenm, filepath) except FeedError as e: logger.warning(f"[kosha] 첨부 실패 skip ({boardno}/{filenm}): {e}") + + # 케이스 단위 commit (R4) — 이후 페이지/케이스의 _api_get 실패가 앞서 적재한 + # 케이스까지 전체 rollback 하지 않게 부분 적재 보존 (csb/api_standards idiom). + await session.commit() if page_all_dup: break # 등록일 역순 — 페이지 전체가 기존이면 이후 페이지도 기존 @@ -374,6 +378,8 @@ async def collect_fatal_accidents(session) -> int: await enqueue_stage(session, doc.id, "embed") await enqueue_stage(session, doc.id, "chunk") new_count += 1 + # 케이스 단위 commit (R4) — 이후 페이지 실패가 앞 케이스 전체 rollback 방지. + await session.commit() if page_all_dup: break # 등록일 역순 — 페이지 전체가 기존이면 이후 페이지도 기존 @@ -450,6 +456,8 @@ async def collect_kosha_guide(session, cap: int = _GUIDE_DAILY_CAP) -> int: await session.flush() await enqueue_stage(session, doc.id, "extract") ingested += 1 + # 항목 단위 commit (R4) — 다운로드 실패가 앞서 적재한 GUIDE 항목 전체 rollback 방지. + await session.commit() # silent cap 금지 — 잔량 가시화 (자동 점진 백필: 내일 cap 만큼 또 소화) logger.info(f"[kosha] GUIDE 신규/개정 {len(new_specs)}건 중 {ingested}건 ingest"