ai-coding-mines목차GitHub

`400`의 사유는 예외 객체가 들고 있다

Python · DB

증상

메시지 발송 API가 400 Bad Request. 본문 형식을 의심해 이스케이프·길이·특수문자를 계속 만졌다. 전부 헛수고였다.

원인

응답 본문에 사유가 있었다.

{"description": "Bad Request: PEER_FLOOD"}

짧은 시간 과다 발송에 대한 발신자 단위 제한이었다. 내용과 무관하다. HTTPError를 잡고 상태코드만 꺼낸 뒤 본문을 버리고 있었다.

★★ 예외 객체는 응답을 들고 있다. e.read() 한 줄이면 나온다. 상태코드만 보면 사유가 통째로 사라진다.

판별 — 같은 입력을 다른 발신자로

같은 본문을 다른 발신자로 보내니 성공했다. 그게 "내용 문제가 아니다"의 증거다.

한 변인만 바꿔 재현해보면 내용 문제와 상태 문제가 갈린다.

대응 — 3단계

  1. 발송 성공 후 고정 간격 대기
  2. 제한 감지 시 더 긴 대기 후 재시도
  3. 그래도 실패하면 다른 발신자로 대체 발송

★ 채널을 성격별로 나눠뒀던 것이 여기서 가용성 이중화가 됐다. 분리는 그 자체로 대체 경로를 만든다 — 발신자가 하나였으면 3단계가 없다.

★★ 곁가지 — 테스트가 운영 쿼터를 소모한다

이 제한에 걸린 계기는 테스트였다. 멱등성 파일(이미 처리한 목록)을 반복해서 비우며 돌렸더니, 같은 알림을 몇 번이고 다시 보내게 됐다.

★★ 외부 쿼터를 쓰는 대상을 테스트할 때, "처리 기록을 비우고 다시 돌린다"는 방식은 발송량을 곱한다. 테스트가 운영을 망가뜨리는 경로다. 쿼터를 쓰지 않는 더미 수신자를 따로 둔다.