#[derive(Debug, thiserror::Error)] pub enum ChannelError { #[error("unauthorized")] Unauthorized, #[error("token invalid or expired")] TokenInvalidOrExpired, #[error("renewal limit exceeded")] RenewalLimitExceeded, #[error("rate limit exceeded")] RateLimitExceeded, #[error("room not found")] RoomNotFound, #[error("user not found")] UserNotFound, #[error("access denied")] AccessDenied, #[error("validation failed: {0}")] Validation(String), #[error("internal error: {0}")] Internal(String), #[error("database failed: {0}")] Database(#[from] db::sqlx::Error), #[error("cache failed: {0}")] Cache(#[from] cache::CacheError), #[error("socket.io failed: {0}")] SocketIo(#[from] socketio::SocketIoError), #[error("serialization failed: {0}")] Serialization(#[from] serde_json::Error), #[error("redis failed: {0}")] Redis(#[from] redis::RedisError), #[error("storage failed: {0}")] Storage(#[from] storage::StorageError), } impl ChannelError { pub fn ws_error_code(&self) -> (u16, &'static str) { match self { ChannelError::Unauthorized => (401, "unauthorized"), ChannelError::TokenInvalidOrExpired => (401, "token_invalid"), ChannelError::AccessDenied => (403, "access_denied"), ChannelError::Validation(_) => (422, "validation_failed"), ChannelError::RateLimitExceeded => (429, "rate_limit_exceeded"), ChannelError::RoomNotFound => (404, "not_found"), ChannelError::UserNotFound => (404, "user_not_found"), ChannelError::RenewalLimitExceeded => (429, "renewal_limit"), ChannelError::Internal(_) => (500, "internal_error"), ChannelError::Database(_) => (500, "internal_error"), ChannelError::Cache(_) => (500, "internal_error"), ChannelError::SocketIo(_) => (500, "internal_error"), ChannelError::Serialization(_) => (500, "internal_error"), ChannelError::Redis(_) => (500, "internal_error"), ChannelError::Storage(_) => (500, "internal_error"), } } pub fn to_ws_error(&self) -> crate::http::out_event::WsError { let (code, error_type) = self.ws_error_code(); crate::http::out_event::WsError { code: code as i32, error: error_type.to_string(), message: self.to_string(), } } } pub type ChannelResult = Result;