배경
`internal/processor/fetcher/worker/retry_scheduler.go` 의 `pollOnce` 는 매 polling tick 마다 due 항목 유무를 DEBUG 로그로 남긴다. 의도는 retry pipeline 의 liveness 확인 — "polling 이 살아있는가" 를 운영자가 즉답할 수 있도록.
현재 동작
```go
if len(due) > 0 {
s.log.WithFields(...).Debug("retry peek returned due items")
} else {
s.log.WithFields(...).Debug("retry peek returned no due items")
}
```
- `PollInterval` default = 1s
- 따라서 idle 상태에서도 매 초 "retry peek returned no due items" 가 1줄씩 찍힘
문제 — 오해 소지
라이브 로그 분석 결과:
| 지표 |
값 |
| 라이브 시간 |
175 분 |
| `no due items` 로그 빈도 |
10,464 건 |
| `due items` 로그 빈도 |
25 건 |
| 비율 |
99.76% 가 빈 tick |
| 전체 debug.log 의 24% 가 본 메시지 |
|
- "returned no due items" 라는 표현이 peek 동작이 일어났다 는 인상을 주어, 10k 건 = 10k 번의 retry 처리가 발생한 것처럼 보임 (실제로는 idle heartbeat)
- 의미 있는 다른 로그를 묻어버려 운영 분석 시 노이즈
변경 제안
- idle heartbeat 압축 — `HeartbeatEveryNIdleTicks int` 신규 Config 필드
- default: 60 (1s polling 기준 ~1분에 1회 heartbeat)
- 0: legacy (매 tick 로깅)
- heartbeat 시 `consecutive_idle_ticks` 필드로 "몇 tick 동안 idle 이었는지" 노출
- 메시지 명 변경:
- `"retry peek returned no due items"` → `"retry pipeline idle heartbeat"`
- heartbeat 임을 메시지 자체에서 식별 가능
- due 발견 시점 로그는 그대로 유지 — 25 건만 찍히던 정상 신호는 압축 X
- env 노출: `.env.example` 에 `RETRY_HEARTBEAT_EVERY_N_IDLE_TICKS` 추가 (현재 RetryScheduler 자체는 `cmd` 에서 `DefaultRedisRetrySchedulerConfig()` 로만 구성 — env 와이어링은 본 PR 의 부수 작업)
완료 조건
영향 / 위험
- DEBUG 로그 양 ~99% 감소 (idle 케이스)
- 운영자 입장 — heartbeat 가 1초 → 1분 주기로 길어지므로 "polling alive" 신호 확인이 60초 늦어질 수 있음. `consecutive_idle_ticks` 필드로 보완.
- legacy 동작 유지 옵션 (N=0) 으로 운영 회귀 안전성 확보
배경
`internal/processor/fetcher/worker/retry_scheduler.go` 의 `pollOnce` 는 매 polling tick 마다 due 항목 유무를 DEBUG 로그로 남긴다. 의도는 retry pipeline 의 liveness 확인 — "polling 이 살아있는가" 를 운영자가 즉답할 수 있도록.
현재 동작
```go
if len(due) > 0 {
s.log.WithFields(...).Debug("retry peek returned due items")
} else {
s.log.WithFields(...).Debug("retry peek returned no due items")
}
```
문제 — 오해 소지
라이브 로그 분석 결과:
변경 제안
완료 조건
영향 / 위험