배경
DevLog_iOS run #29677641610에서 Discord webhook request for pair feat/#734 ↔ test/#701-rn fragment 1 failed with status 429 오류가 발생함.
#50에서 구성한 17개 분할 메시지 중 9개만 Discord에 전달되고, 10번째 메시지가 429를 반환한 뒤 나머지 7개는 전송되지 않음.
#51에서 전체 report가 GitHub Actions Summary에는 보존되지만, Discord에는 일부 report만 남는 부분 전송 상태가 발생함.
현재 Watcher는 Discord 응답 제한 정보에 따른 대기나 재시도 없이 첫 실패를 즉시 상위로 전달함. 재시도를 모두 소진한 뒤에는 현재와 동일하게 Watcher job 실패를 유지해야 함.
작업 범위
src/reportChannels/reportChannel.ts의 Discord 전송 경계에서 429 전용 재시도 추가
- 실패한 동일 fragment를 재시도한 뒤 성공한 경우에만 다음 fragment 전송
429 응답의 숫자형 Retry-After 헤더를 우선 사용하고, 사용할 수 없으면 Discord JSON retry_after 값 사용
- 성공 응답에서
X-RateLimit-Remaining: 0이 확인되면 X-RateLimit-Reset-After만큼 기다린 뒤 다음 fragment 전송
- Discord 제한값을 고정된 요청 횟수로 가정하지 않고 응답의 상대 대기시간 사용
- fragment마다 최대 3회 재시도
- Discord 전송 전체 60초 대기 예산 적용 (
429 재시도 대기와 X-RateLimit-Reset-After 기반 bucket reset 대기 합산)
Retry-After, retry_after, X-RateLimit-Reset-After로 계산한 다음 대기시간이 남은 전체 예산을 초과하거나 유효한 대기시간을 얻을 수 없으면 일찍 재요청하지 않고 즉시 실패
- 재시도를 모두 소진하면 기존과 같이
ReportChannelResult 실패를 반환하고 Watcher job 실패 유지
- 최종 오류에 기존
pair label, fragment number, HTTP status와 재시도 소진 여부 포함
- 오류에서 Discord webhook URL과 응답 본문을 노출하지 않는 기존 보호 유지
README.md의 report channel 설명과 문제 해결 항목에 429 대기·재시도·최종 실패 동작 추가
제외 범위
- Discord report Markdown 생성과 구조 변경
src/reportChannels/discordMessageSplitter.ts의 분할 규칙 변경
429 외 HTTP 상태의 재시도
ReportChannelResult와 공개 함수 시그니처 변경
- reusable workflow input, secret 이름과 권한 변경
- GitHub Actions Summary와 stdout fallback 정책 변경
- AI 예측, deterministic merge risk와 report 내용 변경
완료 기준
429이 발생한 동일 fragment가 성공하거나 재시도를 소진할 때까지 다음 fragment를 전송하지 않음
- 성공 응답에서 bucket 소진이 확인되면 다음 fragment 전송 전 reset 시간을 준수함
429 외 실패는 기존처럼 즉시 실패함
- fragment별 재시도 횟수 한도와 Discord 전송 전체 60초 대기 예산을 준수함
429 재시도 대기와 성공 응답 뒤 bucket reset 대기를 동일한 전체 예산에 합산함
- 재시도 소진 뒤 Discord 부분 전송을 성공으로 처리하지 않고 Watcher job 실패를 유지함
- GitHub Actions Summary에는 Discord 결과와 관계없이 전체 report가 보존됨
- 기존 fragment 순서와 실패 위치 정보가 유지됨
- webhook URL과 Discord 응답 본문이 오류에 노출되지 않음
- 공개 report channel 및 reusable workflow 계약이 변경되지 않음
- README에 실제 동작이 반영됨
검증
Retry-After 숫자 헤더 우선 적용 테스트
- JSON
retry_after fallback 테스트
- 성공 응답의 bucket 소진 후 다음 fragment 대기 테스트
- 동일 fragment 재시도와 다음 fragment 순서 테스트
- fragment별 최대 3회 재시도 테스트
Retry-After, retry_after, X-RateLimit-Reset-After 대기 합산 기준 60초 전체 예산 초과 테스트
- 누락되거나 유효하지 않은 대기시간 처리 테스트
500 등 429 외 상태의 즉시 실패 회귀 테스트
- 최종 오류의 pair label, fragment number, status와 재시도 소진 정보 테스트
- webhook URL과 응답 본문 비노출 테스트
- GitHub Actions Summary와 stdout 보존 테스트
npm run build 통과
npm test 통과
배경
DevLog_iOS run #29677641610에서
Discord webhook request for pair feat/#734 ↔ test/#701-rn fragment 1 failed with status 429오류가 발생함.#50에서 구성한 17개 분할 메시지 중 9개만 Discord에 전달되고, 10번째 메시지가
429를 반환한 뒤 나머지 7개는 전송되지 않음.#51에서 전체 report가 GitHub Actions Summary에는 보존되지만, Discord에는 일부 report만 남는 부분 전송 상태가 발생함.
현재 Watcher는 Discord 응답 제한 정보에 따른 대기나 재시도 없이 첫 실패를 즉시 상위로 전달함. 재시도를 모두 소진한 뒤에는 현재와 동일하게 Watcher job 실패를 유지해야 함.
작업 범위
src/reportChannels/reportChannel.ts의 Discord 전송 경계에서429전용 재시도 추가429응답의 숫자형Retry-After헤더를 우선 사용하고, 사용할 수 없으면 Discord JSONretry_after값 사용X-RateLimit-Remaining: 0이 확인되면X-RateLimit-Reset-After만큼 기다린 뒤 다음 fragment 전송429재시도 대기와X-RateLimit-Reset-After기반 bucket reset 대기 합산)Retry-After,retry_after,X-RateLimit-Reset-After로 계산한 다음 대기시간이 남은 전체 예산을 초과하거나 유효한 대기시간을 얻을 수 없으면 일찍 재요청하지 않고 즉시 실패ReportChannelResult실패를 반환하고 Watcher job 실패 유지pair label,fragment number, HTTP status와 재시도 소진 여부 포함README.md의 report channel 설명과 문제 해결 항목에429대기·재시도·최종 실패 동작 추가제외 범위
src/reportChannels/discordMessageSplitter.ts의 분할 규칙 변경429외 HTTP 상태의 재시도ReportChannelResult와 공개 함수 시그니처 변경완료 기준
429이 발생한 동일 fragment가 성공하거나 재시도를 소진할 때까지 다음 fragment를 전송하지 않음429외 실패는 기존처럼 즉시 실패함429재시도 대기와 성공 응답 뒤 bucket reset 대기를 동일한 전체 예산에 합산함검증
Retry-After숫자 헤더 우선 적용 테스트retry_afterfallback 테스트Retry-After,retry_after,X-RateLimit-Reset-After대기 합산 기준 60초 전체 예산 초과 테스트500등429외 상태의 즉시 실패 회귀 테스트npm run build통과npm test통과