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("CoinAPI file I/O failed: {0}")]
39 Io(#[from] std::io::Error),
40 #[error("Invalid CoinAPI request: {0}")]
41 Validation(String),
42 #[error("Unexpected CoinAPI response: {0}")]
43 Response(String),
44 #[error("CoinAPI credit budget exhausted")]
45 CreditBudget,
46 #[error("CoinAPI retry control: {0}")]
47 Retry(RetryError),
48}
49
50impl Error {
51 #[must_use]
53 pub fn is_retryable(&self) -> bool {
54 match self {
55 Self::Transport(
56 HttpClientError::TransportError(_) | HttpClientError::TimeoutError(_),
57 )
58 | Self::Retry(RetryError::OperationTimeout { .. }) => true,
59 Self::Http { status, .. } | Self::Venue { status, .. } => {
60 *status == 429 || matches!(status, 500 | 502 | 503 | 504)
61 }
62 _ => false,
63 }
64 }
65
66 pub(super) fn retry_delay(&self) -> Option<std::time::Duration> {
67 match self {
68 Self::Http {
69 retry_after_secs, ..
70 }
71 | Self::Venue {
72 retry_after_secs, ..
73 } => retry_after_secs.map(std::time::Duration::from_secs),
74 _ => None,
75 }
76 }
77}