배경
라이브 분석에서 fetcher pool 활용도 측정:
| Pool |
Workers |
Peak Busy |
Utilization |
| normal |
6 |
6/6 |
100% (saturated) |
| chromedp |
2 |
2/2 |
100% (saturated) |
| high |
3 |
0 |
0% (idle) |
| low |
2 |
0 |
0% (idle) |
원인: `SourcePriorityResolver` / `RuleBasedPriorityResolver` 둘 다 등록 룰 0개 → 모든 job 이 `DefaultPriorityResolver` 의 Normal 로 흘러감. high (3) + low (2) = 5 worker idle.
본 메타 이슈는 priority 결정을 정적 카테고리 → 동적 score → 운영자 override 의 3단계로 진화시켜 high/low pool 을 의미 있게 활용하고, 호스트 별 특성에 따라 자동 분배를 가능하게 한다.
3-tier semantic
| Tier |
의미 |
카테고리 / 후보 |
| High |
시의성 + 사회적 영향 高 |
실시간 뉴스 / 정치 / 경제 / 시사 / 사회 |
| Normal |
일반 갱신 + retry |
일반 카테고리 (스포츠/문화/IT/연예/생활/국제), 커뮤니티 article, retry 작업, 신규 host 첫 cycle |
| Low |
광범위 탐색 / discovery |
사이트맵, category hub traverse, pagination 깊은 페이지, 백필 |
단계별 진화 (Sub-issues)
Sub A — CategoryBased + Retry (즉시 가치)
정적 카테고리 + Target.Type 기반 분류. 운영자 매핑 0개 의존하지 않고 3개 tier 모두 활용 시작.
`RetryPriorityResolver` 도 함께 추가 — RetryCount>0 → Normal 강제 (reparse cycle 안정성).
Sub B — Host signal scoring (Normal ↔ High 동적)
Low 후보는 CategoryBased 가 담당. scoring 은 High vs Normal 만 결정.
Signal: freshness / impact / cost / reliability + host 신뢰도.
구현 영역: signal 수집 인프라, `host_scoring_state` 테이블, Redis cache, 5분 주기 scorer goroutine, `DynamicScorePriorityResolver`.
Weight 는 cluster-wide env (per-host 는 Sub C 에서).
Sub C — Per-host hyperparameter + time-bound override
- per-host signal weight — host 마다 weight 다르게 책정
- `fetcher_rules.priority_config` JSONB 신규 컬럼
- 운영자 explicit base_priority override
- `override_until` (time-bound)
- env-only 운영 인터페이스
Resolver chain 최종 구상
```
- ExplicitPriorityResolver (job.Priority 명시 시 — 기존)
- RetryPriorityResolver NEW (RetryCount>0 → Normal — Sub A)
- OverridePriorityResolver NEW (fetcher_rules.priority_config.base_priority — Sub C)
- CategoryBasedResolver NEW (Target.Type / host category — Sub A)
- DynamicScorePriorityResolver NEW (host_scoring_state → High vs Normal — Sub B)
- SourcePriorityResolver (기존, backward compat)
- RuleBasedPriorityResolver (기존, backward compat)
- DefaultPriorityResolver (Low fallback — cold-start, Sub A 도입과 함께 Normal → Low 로 변경)
```
운영 결정 (사용자 확정)
- 시스템 자체 작업 (refinement / stale relearn) → 다른 루트로 처리 중 → priority 분리 X
- Weight 운영 인터페이스 → env-only
- Cold-start → Low (DefaultPriorityResolver fallback 변경)
- Manual override → time-bound 지원
- Signal weight → per-host 책정
완료 조건 (전체)
참고
배경
라이브 분석에서 fetcher pool 활용도 측정:
원인: `SourcePriorityResolver` / `RuleBasedPriorityResolver` 둘 다 등록 룰 0개 → 모든 job 이 `DefaultPriorityResolver` 의 Normal 로 흘러감. high (3) + low (2) = 5 worker idle.
본 메타 이슈는 priority 결정을 정적 카테고리 → 동적 score → 운영자 override 의 3단계로 진화시켜 high/low pool 을 의미 있게 활용하고, 호스트 별 특성에 따라 자동 분배를 가능하게 한다.
3-tier semantic
단계별 진화 (Sub-issues)
Sub A — CategoryBased + Retry (즉시 가치)
정적 카테고리 + Target.Type 기반 분류. 운영자 매핑 0개 의존하지 않고 3개 tier 모두 활용 시작.
`RetryPriorityResolver` 도 함께 추가 — RetryCount>0 → Normal 강제 (reparse cycle 안정성).
Sub B — Host signal scoring (Normal ↔ High 동적)
Low 후보는 CategoryBased 가 담당. scoring 은 High vs Normal 만 결정.
Signal: freshness / impact / cost / reliability + host 신뢰도.
구현 영역: signal 수집 인프라, `host_scoring_state` 테이블, Redis cache, 5분 주기 scorer goroutine, `DynamicScorePriorityResolver`.
Weight 는 cluster-wide env (per-host 는 Sub C 에서).
Sub C — Per-host hyperparameter + time-bound override
Resolver chain 최종 구상
```
```
운영 결정 (사용자 확정)
완료 조건 (전체)
참고