Skip to main content

ringkernel_ecosystem/
error.rs

1//! Error types for ecosystem integrations.
2
3use thiserror::Error;
4
5/// Ecosystem integration error type.
6#[derive(Error, Debug)]
7pub enum EcosystemError {
8    /// RingKernel core error.
9    #[error("RingKernel error: {0}")]
10    RingKernel(#[from] ringkernel_core::error::RingKernelError),
11
12    /// Timeout waiting for response.
13    #[error("Operation timed out after {0:?}")]
14    Timeout(std::time::Duration),
15
16    /// Kernel not found.
17    #[error("Kernel not found: {0}")]
18    KernelNotFound(String),
19
20    /// Invalid configuration.
21    #[error("Configuration error: {0}")]
22    Config(String),
23
24    /// Serialization error.
25    #[error("Serialization error: {0}")]
26    Serialization(String),
27
28    /// Deserialization error.
29    #[error("Deserialization error: {0}")]
30    Deserialization(String),
31
32    /// Data conversion error.
33    #[error("Data conversion error: {0}")]
34    DataConversion(String),
35
36    /// Service unavailable.
37    #[error("Service unavailable: {0}")]
38    ServiceUnavailable(String),
39
40    /// Internal error.
41    #[error("Internal error: {0}")]
42    Internal(String),
43
44    /// Actor error (for actix integration).
45    #[cfg(feature = "actix")]
46    #[error("Actor error: {0}")]
47    Actor(String),
48
49    /// gRPC error (for tonic integration).
50    #[cfg(feature = "grpc")]
51    #[error("gRPC error: {0}")]
52    Grpc(String),
53
54    /// Arrow error (for arrow integration).
55    #[cfg(feature = "arrow")]
56    #[error("Arrow error: {0}")]
57    Arrow(String),
58
59    /// Polars error (for polars integration).
60    #[cfg(feature = "polars")]
61    #[error("Polars error: {0}")]
62    Polars(String),
63
64    /// Candle error (for ML integration).
65    #[cfg(feature = "candle")]
66    #[error("Candle error: {0}")]
67    Candle(String),
68
69    /// Persistent kernel error (for persistent integration).
70    #[cfg(feature = "persistent")]
71    #[error("Persistent kernel error: {0}")]
72    Persistent(String),
73
74    /// Command queue full.
75    #[cfg(feature = "persistent")]
76    #[error("Command queue full")]
77    QueueFull,
78
79    /// Kernel not running.
80    #[cfg(feature = "persistent")]
81    #[error("Kernel not running: {0}")]
82    KernelNotRunning(String),
83
84    /// Command failed with error code.
85    #[cfg(feature = "persistent")]
86    #[error("Command failed (code {code}): {message}")]
87    CommandFailed {
88        /// Error code from kernel.
89        code: u32,
90        /// Error message.
91        message: String,
92    },
93}
94
95/// Result type for ecosystem operations.
96pub type Result<T> = std::result::Result<T, EcosystemError>;
97
98/// Error that can be returned from Axum handlers.
99#[cfg(feature = "axum")]
100#[derive(Debug)]
101pub struct AppError(pub EcosystemError);
102
103#[cfg(feature = "axum")]
104impl std::fmt::Display for AppError {
105    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
106        write!(f, "{}", self.0)
107    }
108}
109
110#[cfg(feature = "axum")]
111impl std::error::Error for AppError {}
112
113#[cfg(feature = "axum")]
114impl axum::response::IntoResponse for AppError {
115    fn into_response(self) -> axum::response::Response {
116        use axum::http::StatusCode;
117
118        let status = match &self.0 {
119            EcosystemError::KernelNotFound(_) => StatusCode::NOT_FOUND,
120            EcosystemError::Timeout(_) => StatusCode::GATEWAY_TIMEOUT,
121            EcosystemError::Config(_) => StatusCode::BAD_REQUEST,
122            EcosystemError::ServiceUnavailable(_) => StatusCode::SERVICE_UNAVAILABLE,
123            _ => StatusCode::INTERNAL_SERVER_ERROR,
124        };
125
126        (status, self.0.to_string()).into_response()
127    }
128}
129
130#[cfg(feature = "axum")]
131impl From<EcosystemError> for AppError {
132    fn from(err: EcosystemError) -> Self {
133        AppError(err)
134    }
135}
136
137#[cfg(feature = "grpc")]
138impl From<EcosystemError> for tonic::Status {
139    fn from(err: EcosystemError) -> Self {
140        use tonic::Code;
141
142        let code = match &err {
143            EcosystemError::KernelNotFound(_) => Code::NotFound,
144            EcosystemError::Timeout(_) => Code::DeadlineExceeded,
145            EcosystemError::Config(_) => Code::InvalidArgument,
146            EcosystemError::ServiceUnavailable(_) => Code::Unavailable,
147            _ => Code::Internal,
148        };
149
150        tonic::Status::new(code, err.to_string())
151    }
152}