Skip to main content

lightcone_sdk/websocket/
error.rs

1//! WebSocket-specific error types for the Lightcone SDK.
2
3use thiserror::Error;
4
5/// WebSocket-specific errors
6#[derive(Debug, Clone, Error)]
7pub enum WebSocketError {
8    /// Initial connection failure
9    #[error("Connection failed: {0}")]
10    ConnectionFailed(String),
11
12    /// Unexpected connection close
13    #[error("Connection closed unexpectedly: code {code}, reason: {reason}")]
14    ConnectionClosed { code: u16, reason: String },
15
16    /// Rate limited (close code 1008)
17    #[error("Rate limited: too many connections from this IP")]
18    RateLimited,
19
20    /// JSON deserialization failure
21    #[error("Failed to parse message: {0}")]
22    MessageParseError(String),
23
24    /// Detected sequence gap in book updates
25    #[error("Sequence gap detected: expected {expected}, received {received}")]
26    SequenceGap { expected: u64, received: u64 },
27
28    /// Server requested resync
29    #[error("Resync required for orderbook: {orderbook_id}")]
30    ResyncRequired { orderbook_id: String },
31
32    /// Subscription error from server
33    #[error("Subscription failed: {0}")]
34    SubscriptionFailed(String),
35
36    /// Client ping not responded
37    #[error("Ping timeout: no pong response received")]
38    PingTimeout,
39
40    /// WebSocket protocol error
41    #[error("WebSocket protocol error: {0}")]
42    Protocol(String),
43
44    /// Server returned an error
45    #[error("Server error: {message} (code: {code})")]
46    ServerError { code: String, message: String },
47
48    /// Not connected
49    #[error("Not connected to WebSocket server")]
50    NotConnected,
51
52    /// Already connected
53    #[error("Already connected to WebSocket server")]
54    AlreadyConnected,
55
56    /// Send failed
57    #[error("Failed to send message: {0}")]
58    SendFailed(String),
59
60    /// Channel closed
61    #[error("Internal channel closed")]
62    ChannelClosed,
63
64    /// Invalid URL
65    #[error("Invalid WebSocket URL: {0}")]
66    InvalidUrl(String),
67
68    /// Timeout
69    #[error("Operation timed out")]
70    Timeout,
71
72    /// IO error
73    #[error("IO error: {0}")]
74    Io(String),
75
76    /// Authentication failed
77    #[error("Authentication failed: {0}")]
78    AuthenticationFailed(String),
79
80    /// Authentication required for user stream
81    #[error("Authentication required for user stream")]
82    AuthRequired,
83
84    /// HTTP request error
85    #[error("HTTP request error: {0}")]
86    HttpError(String),
87
88    /// Invalid auth token
89    #[error("Invalid auth token: {0}")]
90    InvalidAuthToken(String),
91}
92
93impl From<tokio_tungstenite::tungstenite::Error> for WebSocketError {
94    fn from(err: tokio_tungstenite::tungstenite::Error) -> Self {
95        use tokio_tungstenite::tungstenite::Error;
96        match err {
97            Error::ConnectionClosed => WebSocketError::ConnectionClosed {
98                code: 1000,
99                reason: "Connection closed normally".to_string(),
100            },
101            Error::AlreadyClosed => WebSocketError::NotConnected,
102            Error::Io(e) => WebSocketError::Io(e.to_string()),
103            Error::Protocol(e) => WebSocketError::Protocol(e.to_string()),
104            Error::Url(e) => WebSocketError::InvalidUrl(e.to_string()),
105            Error::Http(resp) => {
106                WebSocketError::ConnectionFailed(format!("HTTP error: {:?}", resp.status()))
107            }
108            Error::HttpFormat(e) => WebSocketError::ConnectionFailed(e.to_string()),
109            other => WebSocketError::Protocol(other.to_string()),
110        }
111    }
112}
113
114impl From<serde_json::Error> for WebSocketError {
115    fn from(err: serde_json::Error) -> Self {
116        WebSocketError::MessageParseError(err.to_string())
117    }
118}
119
120impl From<reqwest::Error> for WebSocketError {
121    fn from(err: reqwest::Error) -> Self {
122        WebSocketError::HttpError(err.to_string())
123    }
124}
125
126impl<T> From<tokio::sync::mpsc::error::SendError<T>> for WebSocketError {
127    fn from(_: tokio::sync::mpsc::error::SendError<T>) -> Self {
128        WebSocketError::ChannelClosed
129    }
130}
131
132/// Result type alias for WebSocket operations
133pub type WsResult<T> = Result<T, WebSocketError>;