1use orcs_runtime::{ChannelError, EngineError, StorageError};
6use orcs_types::ErrorCode;
7use thiserror::Error;
8
9#[derive(Debug, Error)]
27pub enum AppError {
28 #[error("Channel error: {0}")]
30 Channel(#[from] ChannelError),
31
32 #[error("Engine error: {0}")]
34 Engine(#[from] EngineError),
35
36 #[error("Config error: {0}")]
38 Config(String),
39
40 #[error("IO error: {0}")]
42 Io(#[from] std::io::Error),
43
44 #[error("Not initialized: {0}")]
46 NotInitialized(String),
47
48 #[error("Storage error: {0}")]
50 Storage(#[from] StorageError),
51}
52
53impl ErrorCode for AppError {
54 fn code(&self) -> &'static str {
55 match self {
56 Self::Channel(e) => e.code(),
57 Self::Engine(e) => e.code(),
58 Self::Config(_) => "APP_CONFIG_ERROR",
59 Self::Io(_) => "APP_IO_ERROR",
60 Self::NotInitialized(_) => "APP_NOT_INITIALIZED",
61 Self::Storage(_) => "APP_STORAGE_ERROR",
62 }
63 }
64
65 fn is_recoverable(&self) -> bool {
66 match self {
67 Self::Channel(e) => e.is_recoverable(),
68 Self::Engine(e) => e.is_recoverable(),
69 Self::Config(_) => false,
70 Self::Io(_) => true,
71 Self::NotInitialized(_) => false,
72 Self::Storage(_) => true,
73 }
74 }
75}
76
77#[cfg(test)]
78mod tests {
79 use super::*;
80 use orcs_types::ChannelId;
81
82 #[test]
83 fn channel_error_converts() {
84 let err = ChannelError::NotFound(ChannelId::new());
85 let app_err: AppError = err.into();
86 assert!(matches!(app_err, AppError::Channel(_)));
87 }
88
89 #[test]
90 fn error_codes() {
91 let err = AppError::Config("test".into());
92 assert_eq!(err.code(), "APP_CONFIG_ERROR");
93 assert!(!err.is_recoverable());
94 }
95}