Go
오류와 재시도
모든 실패에 하나의 오류 타입, 종류마다 하나의 센티널, 그리고 두 번 보내지 않는 재시도.
오류 처리하기
_, err := client.Emails.Send(ctx, openemail.Body{ "from": "[email protected]", "to": "[email protected]", "subject": "Your September invoice", "text": "Invoice attached.",}) var failure *openemail.Error switch {case err == nil: fmt.Println("sent")case errors.Is(err, openemail.ErrValidation): errors.As(err, &failure) fmt.Println(failure.Code, failure.Param, failure.Message)case errors.Is(err, openemail.ErrRateLimited): errors.As(err, &failure) fmt.Println("try again in", failure.RetryAfter)case errors.Is(err, openemail.ErrTimeout): fmt.Println("no answer in time")default: return err}모든 실패는 *openemail.Error입니다. errors.Is는 어떤 종류인지 알려 주고, errors.As는 API가 알려 준 내용과 함께 오류 자체를 제공합니다.
| 항목 | 담긴 내용 |
|---|---|
| Status | HTTP 상태이며, 응답이 오지 않았으면 0입니다. |
| Type, Code | API의 오류 타입과 코드. 예를 들어 validation_error와 invalid_parameter입니다. |
| Param | 문제가 된 필드. 있는 경우에만 들어 있습니다. |
| RequestID | 지원팀에 문의할 때 알려 줄 id입니다. |
| DocURL | 해당 코드를 설명하는 문서 페이지입니다. |
| RetryAfter | API가 기다리라고 요청한 시간입니다. |
| Fields | 가입 양식이 거부한 필드. 각각 Key와 Error가 있습니다. |
| Body | 디코딩된 응답 본문입니다. |
실패의 종류
| 센티널 | 일치하는 경우 |
|---|---|
| ErrAuthentication | 키 또는 토큰이 거부되었습니다. 401입니다. |
| ErrPermission | 이 자격 증명으로는 할 수 없는 작업입니다. 403입니다. |
| ErrScopeMissing | 호출에 필요한 스코프가 자격 증명에 없습니다. |
| ErrStepUpRequired | 액세스 토큰이 먼저 코드를 인증해야 합니다. |
| ErrNotFound | 해당 id를 가진 것이 없습니다. 404입니다. |
| ErrConflict | 변경이 현재 상태와 충돌합니다. 409입니다. |
| ErrValidation | 필드가 거부되었습니다. 422입니다. |
| ErrRateLimited | 요청이 너무 많거나 할당량을 모두 썼습니다. 429입니다. |
| ErrInvalidRequest | 요청에 대한 그 밖의 모든 거부입니다. |
| ErrServer | API가 실패했습니다. 상태는 500 이상입니다. |
| ErrRetryable | 클라이언트가 다시 시도하는 상태입니다. |
| ErrNetwork | 응답이 오지 않았습니다. |
| ErrTimeout | 타임아웃 전에 응답이 오지 않았습니다. |
| ErrInvalidArgument | 호출 자체가 잘못되어 아무것도 보내지 않았습니다. |
| ErrWebhookSignature | 웹훅 전달이 확인에 실패했습니다. |
취소된 컨텍스트는 여전히 context.Canceled와 일치하고, 지난 기한은 context.DeadlineExceeded와 일치합니다.
다시 시도되는 것
- 읽기, 발송, 그리고 반복해도 안전한 모든 쓰기는 최대
WithMaxRetries번까지 다시 시도됩니다. 그 밖의 쓰기는 한 번만 보냅니다. - 상태 408, 500, 502, 503, 504는 0.5초에서 시작해 8초까지 두 배씩 늘어나는 대기 시간을 두고 다시 시도됩니다.
- 429는 1분 이하의
Retry-After가 있을 때만 다시 시도되며, 클라이언트는 그 시간만큼 기다립니다. - 실패하거나 타임아웃된 연결도 같은 방식으로 다시 시도됩니다.
다시 시도되는 발송은 매번 같은 멱등성 키를 가지므로, API는 두 번째 메시지를 보내는 대신 첫 메시지를 재생합니다.