use std::time::Duration;
use thiserror::Error;
#[derive(Debug, Clone)]
pub struct ApiError {
pub status: u16,
pub kind: String,
pub message: String,
pub request_id: Option<String>,
pub retry_after: Option<Duration>,
}
#[derive(Debug, Error)]
pub enum Error {
#[error("HTTP transport failure while calling the Messages API")]
Transport(#[source] reqwest::Error),
#[error("could not deserialize the Messages API response body")]
Decode(#[source] serde_json::Error),
#[error("Messages API returned HTTP {} ({}): {}", .0.status, .0.kind, .0.message)]
Api(ApiError),
#[error("unexpected HTTP {status} response from the Messages API: {body}")]
Unexpected {
status: u16,
body: String,
},
}
impl Error {
#[must_use]
pub fn is_retryable(&self) -> bool {
match self {
Error::Transport(_) => true,
Error::Api(api) => matches!(api.status, 429 | 500 | 529),
Error::Unexpected { status, .. } => matches!(status, 429 | 500 | 529),
Error::Decode(_) => false,
}
}
#[must_use]
pub fn retry_after(&self) -> Option<Duration> {
match self {
Error::Api(api) => api.retry_after,
_ => None,
}
}
}