use thiserror::Error;
pub type Result<T> = std::result::Result<T, BatataError>;
#[derive(Error, Debug)]
pub enum BatataError {
#[error("Config not found: dataId={data_id}, group={group}, namespace={namespace}")]
ConfigNotFound {
data_id: String,
group: String,
namespace: String,
},
#[error("Service not found: service={service_name}, group={group_name}, namespace={namespace}")]
ServiceNotFound {
service_name: String,
group_name: String,
namespace: String,
},
#[error("Connection error: {message}")]
ConnectionError { message: String },
#[error("Server error: code={error_code}, message={message}")]
ServerError { error_code: i32, message: String },
#[error("Authentication error: {message}")]
AuthError { message: String },
#[error("Permission denied: {message}")]
PermissionDenied { message: String },
#[error("Request timeout after {timeout_ms}ms")]
Timeout { timeout_ms: u64 },
#[error("Serialization error: {0}")]
SerializationError(#[from] serde_json::Error),
#[error("gRPC transport error: {0}")]
TransportError(#[from] tonic::transport::Error),
#[error("gRPC status error: {0}")]
GrpcStatus(#[from] tonic::Status),
#[error("Invalid parameter: {0}")]
InvalidParameter(String),
#[error("Internal error: {0}")]
Internal(String),
#[error("No available server")]
NoAvailableServer,
#[error("Client not started")]
ClientNotStarted,
#[error("Client already started")]
ClientAlreadyStarted,
#[error("Encryption error: {message}")]
EncryptionError { message: String },
}
impl BatataError {
pub fn is_retryable(&self) -> bool {
matches!(
self,
BatataError::ConnectionError { .. }
| BatataError::Timeout { .. }
| BatataError::TransportError(_)
| BatataError::NoAvailableServer
)
}
pub fn server_error(error_code: i32, message: impl Into<String>) -> Self {
BatataError::ServerError {
error_code,
message: message.into(),
}
}
pub fn connection_error(message: impl Into<String>) -> Self {
BatataError::ConnectionError {
message: message.into(),
}
}
}