use thiserror::Error;
#[derive(Error, Debug)]
pub enum EcosystemError {
#[error("RingKernel error: {0}")]
RingKernel(#[from] ringkernel_core::error::RingKernelError),
#[error("Operation timed out after {0:?}")]
Timeout(std::time::Duration),
#[error("Kernel not found: {0}")]
KernelNotFound(String),
#[error("Configuration error: {0}")]
Config(String),
#[error("Serialization error: {0}")]
Serialization(String),
#[error("Deserialization error: {0}")]
Deserialization(String),
#[error("Data conversion error: {0}")]
DataConversion(String),
#[error("Service unavailable: {0}")]
ServiceUnavailable(String),
#[error("Internal error: {0}")]
Internal(String),
#[cfg(feature = "actix")]
#[error("Actor error: {0}")]
Actor(String),
#[cfg(feature = "grpc")]
#[error("gRPC error: {0}")]
Grpc(String),
#[cfg(feature = "arrow")]
#[error("Arrow error: {0}")]
Arrow(String),
#[cfg(feature = "polars")]
#[error("Polars error: {0}")]
Polars(String),
#[cfg(feature = "candle")]
#[error("Candle error: {0}")]
Candle(String),
#[cfg(feature = "persistent")]
#[error("Persistent kernel error: {0}")]
Persistent(String),
#[cfg(feature = "persistent")]
#[error("Command queue full")]
QueueFull,
#[cfg(feature = "persistent")]
#[error("Kernel not running: {0}")]
KernelNotRunning(String),
#[cfg(feature = "persistent")]
#[error("Command failed (code {code}): {message}")]
CommandFailed {
code: u32,
message: String,
},
}
pub type Result<T> = std::result::Result<T, EcosystemError>;
#[cfg(feature = "axum")]
#[derive(Debug)]
pub struct AppError(pub EcosystemError);
#[cfg(feature = "axum")]
impl std::fmt::Display for AppError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}
#[cfg(feature = "axum")]
impl std::error::Error for AppError {}
#[cfg(feature = "axum")]
impl axum::response::IntoResponse for AppError {
fn into_response(self) -> axum::response::Response {
use axum::http::StatusCode;
let status = match &self.0 {
EcosystemError::KernelNotFound(_) => StatusCode::NOT_FOUND,
EcosystemError::Timeout(_) => StatusCode::GATEWAY_TIMEOUT,
EcosystemError::Config(_) => StatusCode::BAD_REQUEST,
EcosystemError::ServiceUnavailable(_) => StatusCode::SERVICE_UNAVAILABLE,
_ => StatusCode::INTERNAL_SERVER_ERROR,
};
(status, self.0.to_string()).into_response()
}
}
#[cfg(feature = "axum")]
impl From<EcosystemError> for AppError {
fn from(err: EcosystemError) -> Self {
AppError(err)
}
}
#[cfg(feature = "grpc")]
impl From<EcosystemError> for tonic::Status {
fn from(err: EcosystemError) -> Self {
use tonic::Code;
let code = match &err {
EcosystemError::KernelNotFound(_) => Code::NotFound,
EcosystemError::Timeout(_) => Code::DeadlineExceeded,
EcosystemError::Config(_) => Code::InvalidArgument,
EcosystemError::ServiceUnavailable(_) => Code::Unavailable,
_ => Code::Internal,
};
tonic::Status::new(code, err.to_string())
}
}