여러 줄 주석이 설명보다 경위(예전·실측·지적)를 적고 있어 읽는 사람이 결론을 찾기 어려웠다. - ts·tsx·js·mjs·css·py 478개: 여러 줄 주석은 첫 문장 한 줄로, 과거형·날짜 문장은 삭제 - 주석 위치는 TypeScript 파서·파이썬 tokenize/ast 로 찾는다 — 문자열 안의 # · /* 는 건드리지 않는다 - eslint·ts·noqa·type: ignore 같은 지시 주석은 그대로 둔다 파이썬 275개 정리 전후 AST 동일, TS 298개 주석 뺀 토큰 동일(빈 JSX 주석 10곳만 차이). site·frontend·admin tsc, site vitest 105 passed Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
52 lines
1.7 KiB
Python
52 lines
1.7 KiB
Python
"""수집(크롤링) 중 실패를 jobs.result 에 구조화해서 싣는다 — 워커 로그 grep 없이 확인용."""
|
|
from contextlib import contextmanager
|
|
from contextvars import ContextVar
|
|
from dataclasses import asdict, dataclass
|
|
|
|
from common.logger import LOG
|
|
|
|
_current: ContextVar[list["CollectIssue"] | None] = ContextVar("_collect_issues", default=None)
|
|
|
|
# jobs.result 는 DB 에 그대로 쌓인다 — 예외 메시지가 길어지는(HTML 응답 전체를 문 등) 경우가 있어 상한을 둔다.
|
|
_MAX_MESSAGE = 500
|
|
_MAX_TARGET = 200
|
|
|
|
|
|
@dataclass
|
|
class CollectIssue:
|
|
stage: str # 어느 단계에서(예: "naver_place" · "tour_api" · "yanolja" · "static_html")
|
|
target: str # 무엇을 하다가(URL·검색어 등)
|
|
error_type: str # 예외 클래스명
|
|
message: str # 예외 메시지
|
|
|
|
|
|
@contextmanager
|
|
def collecting():
|
|
"""run_collect() 진입부에서 한 번 연다."""
|
|
token = _current.set([])
|
|
try:
|
|
yield
|
|
finally:
|
|
_current.reset(token)
|
|
|
|
|
|
def note_issue(stage: str, target: str, ex: Exception) -> CollectIssue:
|
|
"""실패 한 건을 기록하고 기존과 같은 형식으로 로그도 남긴다."""
|
|
issue = CollectIssue(
|
|
stage=stage,
|
|
target=target[:_MAX_TARGET],
|
|
error_type=type(ex).__name__,
|
|
message=str(ex)[:_MAX_MESSAGE],
|
|
)
|
|
issues = _current.get()
|
|
if issues is not None:
|
|
issues.append(issue)
|
|
LOG.w(f"[collect] {stage} 실패(계속) {issue.target}: {issue.error_type}: {issue.message}")
|
|
return issue
|
|
|
|
|
|
def snapshot() -> list[dict]:
|
|
"""지금까지 쌓인 실패 목록."""
|
|
issues = _current.get()
|
|
return [asdict(i) for i in issues] if issues else []
|