nautilus_coinapi/http/
error.rs1use nautilus_network::{http::HttpClientError, retry::RetryError};
19
20#[derive(Debug, thiserror::Error)]
22pub enum Error {
23 #[error(transparent)]
24 Transport(#[from] HttpClientError),
25 #[error("CoinAPI HTTP status {status}")]
26 Http {
27 status: u16,
28 retry_after_secs: Option<u64>,
29 },
30 #[error("CoinAPI HTTP status {status}: {message}")]
31 Venue {
32 status: u16,
33 message: String,
34 retry_after_secs: Option<u64>,
35 },
36 #[error("CoinAPI response parsing failed: {0}")]
37 Parse(#[from] serde_json::Error),
38 #[error("Invalid CoinAPI request: {0}")]
39 Validation(String),
40 #[error("Unexpected CoinAPI response: {0}")]
41 Response(String),
42 #[error("CoinAPI credit budget exhausted")]
43 CreditBudget,
44 #[error("CoinAPI retry control: {0}")]
45 Retry(RetryError),
46}
47
48impl Error {
49 #[must_use]
51 pub fn is_retryable(&self) -> bool {
52 match self {
53 Self::Transport(
54 HttpClientError::TransportError(_) | HttpClientError::TimeoutError(_),
55 )
56 | Self::Retry(RetryError::OperationTimeout { .. }) => true,
57 Self::Http { status, .. } | Self::Venue { status, .. } => {
58 *status == 429 || matches!(status, 500 | 502 | 503 | 504)
59 }
60 _ => false,
61 }
62 }
63
64 pub(super) fn retry_delay(&self) -> Option<std::time::Duration> {
65 match self {
66 Self::Http {
67 retry_after_secs, ..
68 }
69 | Self::Venue {
70 retry_after_secs, ..
71 } => retry_after_secs.map(std::time::Duration::from_secs),
72 _ => None,
73 }
74 }
75}