부모
부모 이슈: #385
의존: Sub 1
작업 범위
1. `internal/processor/fetcher/worker/retry_scheduler.go` → `internal/publisher/retry.go` 이동
- Redis delayed retry scheduler (peek-publish-ack 패턴) 이동
- 기존 `RedisDelayedRetryScheduler` + `KafkaImmediateRetryScheduler` 둘 다 publisher 측으로
- 외부 인터페이스 `RetryScheduler` 도 publisher 측으로 이동
2. publisher facade 흡수
```go
func (p *Publisher) PublishRetry(ctx, job *core.CrawlJob, lastErr error) error
```
내부적으로 RedisDelayedRetryScheduler.Enqueue 호출 + idle heartbeat polling goroutine 유지.
3. `fetcher/worker/{manager,pool}` 호출처 갱신
- 기존 `retryScheduler.Enqueue` → `publisher.PublishRetry` 변경
- Sub 5 (worker Kafka I/O 분리) 와 충돌 영역 — 본 Sub 가 retry 만 책임 분리
4. main.go wiring
- `crawlerWorker.NewRedisDelayedRetryScheduler` → `publisher.NewRetryScheduler` (또는 facade 내부 생성)
5. 테스트
- 기존 retry_scheduler_test.go 그대로 → `test/internal/publisher/retry_test.go` 로 이동
- KafkaImmediateRetryScheduler 테스트 동일 이동
영향 / 위험
완료 조건
부모
부모 이슈: #385
의존: Sub 1
작업 범위
1. `internal/processor/fetcher/worker/retry_scheduler.go` → `internal/publisher/retry.go` 이동
2. publisher facade 흡수
```go
func (p *Publisher) PublishRetry(ctx, job *core.CrawlJob, lastErr error) error
```
내부적으로 RedisDelayedRetryScheduler.Enqueue 호출 + idle heartbeat polling goroutine 유지.
3. `fetcher/worker/{manager,pool}` 호출처 갱신
4. main.go wiring
5. 테스트
영향 / 위험
완료 조건