feat(news): crawl-24x7 A그룹 — 레지스트리 증축·조건부 GET·fulltext 승격·politeness·source_health
A-3 migrations 319-323 (news_sources 9컬럼 + source_channel 'crawl' + process_stage 'fulltext' + source_health) A-1 조건부 GET(ETag/Last-Modified 그대로 재전송)+콘텐츠 해시 변경감지, A-4 politeness 코어(per-domain 직렬+robots+정직UA), A-2+A-7 fulltext_worker(4-tier 재사용·NAS crawl_raw gzip 보존·격하 경로·03:40 reconcile 안전망), A-5 circuit breaker(3/10 임계, enabled 미터치), A-6 포털 전재 2차 dedup(제목+3일, 12자 게이트). 기존 소스 fulltext_policy='none' 기본 = 무회귀. plan crawl-24x7-1, 예외 박제 crawl-24x7-exec1-20260610.md
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
-- A-3 (plan crawl-24x7-1): 소스 레지스트리 증축 — additive only.
|
||||
-- fetch_method : rss / rss+page / sitemap+page / page / api / signal-only
|
||||
-- fulltext_policy : none(현행 유지) / page(기사 페이지 fetch 후 4-tier 승격) / feed-full(피드 본문이 전문)
|
||||
-- auth_profile : NULL=공개, 값=구독 세션 키 (B-3 Playwright 어댑터용 슬롯)
|
||||
-- poll_interval_minutes : 소스별 차등 폴링 (NULL=전역 6h 사이클)
|
||||
-- etag / last_modified : 조건부 GET 워터마크 — 받은 그대로 저장·재전송 (상태는 전부 DB, APScheduler in-process)
|
||||
-- feed_content_hash : CDN ETag 회전 대비 콘텐츠 해시 변경감지 병행
|
||||
-- selector_override : 추출 실패 잦은 소스의 site-specific CSS selector (JSONB)
|
||||
-- parser_quirk : rdf / table-strip / gn-redirect 등 파서 특이 케이스
|
||||
ALTER TABLE news_sources
|
||||
ADD COLUMN IF NOT EXISTS fetch_method VARCHAR(20) NOT NULL DEFAULT 'rss',
|
||||
ADD COLUMN IF NOT EXISTS fulltext_policy VARCHAR(20) NOT NULL DEFAULT 'none',
|
||||
ADD COLUMN IF NOT EXISTS auth_profile VARCHAR(50),
|
||||
ADD COLUMN IF NOT EXISTS poll_interval_minutes INTEGER,
|
||||
ADD COLUMN IF NOT EXISTS etag TEXT,
|
||||
ADD COLUMN IF NOT EXISTS last_modified TEXT,
|
||||
ADD COLUMN IF NOT EXISTS feed_content_hash VARCHAR(64),
|
||||
ADD COLUMN IF NOT EXISTS selector_override JSONB,
|
||||
ADD COLUMN IF NOT EXISTS parser_quirk VARCHAR(30);
|
||||
@@ -0,0 +1,3 @@
|
||||
-- 0-5 (a) 확정 (plan crawl-24x7-1): 도메인 자료(안전/공학/철학) 채널 신설 — news 와 분리.
|
||||
-- 신규 값은 같은 트랜잭션 내 사용 금지 (PG 제약) — 본 배치의 다른 마이그레이션은 'crawl' 미사용.
|
||||
ALTER TYPE source_channel ADD VALUE IF NOT EXISTS 'crawl';
|
||||
@@ -0,0 +1,3 @@
|
||||
-- A-2 (plan crawl-24x7-1): RSS 요약 → 기사 페이지 fetch → 4-tier 본문 승격 stage.
|
||||
-- fulltext_policy='page' 소스의 기사에만 news_collector 가 enqueue.
|
||||
ALTER TYPE process_stage ADD VALUE IF NOT EXISTS 'fulltext';
|
||||
@@ -0,0 +1,19 @@
|
||||
-- A-5 (plan crawl-24x7-1): 소스 건강 — 소스별 실패 격리 기록 + circuit breaker.
|
||||
-- 한 소스가 죽어도 나머지 영향 0. silent skip 누적 방지의 가시성 기반 (A-8 패널이 읽음).
|
||||
-- circuit_state: closed(정상) / open(연속 실패로 지수 backoff 중) / disabled(M회 초과, 수동 복구 대상)
|
||||
-- empty_streak : 200 인데 entries 0 인 연속 fetch 횟수 (피드 부패 감시 — 304/해시동일은 미집계)
|
||||
CREATE TABLE IF NOT EXISTS source_health (
|
||||
id SERIAL PRIMARY KEY,
|
||||
source_id INTEGER NOT NULL REFERENCES news_sources(id) ON DELETE CASCADE,
|
||||
consecutive_failures INTEGER NOT NULL DEFAULT 0,
|
||||
total_fetches BIGINT NOT NULL DEFAULT 0,
|
||||
total_failures BIGINT NOT NULL DEFAULT 0,
|
||||
last_success_at TIMESTAMPTZ,
|
||||
last_error TEXT,
|
||||
last_error_at TIMESTAMPTZ,
|
||||
last_fetch_items INTEGER,
|
||||
empty_streak INTEGER NOT NULL DEFAULT 0,
|
||||
circuit_state VARCHAR(10) NOT NULL DEFAULT 'closed',
|
||||
circuit_opened_at TIMESTAMPTZ,
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
@@ -0,0 +1,2 @@
|
||||
-- A-5: source_health 는 news_sources 와 1:1 — upsert 기준 키.
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS uq_source_health_source_id ON source_health (source_id);
|
||||
Reference in New Issue
Block a user