Retry 는 시간이 고쳐줄 에러만. Retryable — RateLimitError (429), APIConnectionError (network blip), 5xx server error. Non-retryable — 400 (bad request), 401 (auth), 404, 422. Non-retryable retry 는 같은 벽 다시 치는 거.
tenacity 가 right primitive
@retry(retry=retry_if_exception_type((openai.RateLimitError, openai.APIConnectionError)), wait=wait_exponential_jitter(initial=1, max=20), stop=stop_after_attempt(5)) — 합리적 default. 401 도 retry 박는 코드는 같은 벽 5 번 치고 끝.
Exception class 정확히 보기
SDK 는 APIError 를 base 로 하고 그 아래 APIStatusError, RateLimitError, APIConnectionError 등을 둬. Bare except Exception 은 KeyboardInterrupt 까지 잡아서 디버깅을 망쳐. 정확한 class 로 잡아.
Logging 을 retry hook 에
매 retry 마다 attempt 번호와 실제 wait 를 log. Production 에서 'why is it slow' 답이 나옴 — '실제로 5 번 retry 중이었어' 가 가장 흔한 답.