Mountain/Error/
ServiceError.rs1use std::{error::Error as StdError, fmt};
9
10use serde::{Deserialize, Serialize};
11
12use super::CoreError::{ErrorContext, ErrorKind, ErrorSeverity, MountainError};
13
14#[derive(Debug, Clone, Serialize, Deserialize)]
16pub enum ServiceError {
17 ServiceNotFound { context:ErrorContext, service_name:String },
19
20 InitializationFailed { context:ErrorContext, service_name:String, source:Option<String> },
22
23 AlreadyRunning { context:ErrorContext, service_name:String },
25
26 NotRunning { context:ErrorContext, service_name:String },
28
29 StartFailed { context:ErrorContext, service_name:String, source:Option<String> },
31
32 StopFailed { context:ErrorContext, service_name:String, source:Option<String> },
34
35 Timeout { context:ErrorContext, service_name:String, operation:String, timeout_ms:u64 },
37
38 DependencyError { context:ErrorContext, service_name:String, dependency:String },
40}
41
42impl ServiceError {
43 pub fn context(&self) -> &ErrorContext {
45 match self {
46 ServiceError::ServiceNotFound { context, .. } => context,
47
48 ServiceError::InitializationFailed { context, .. } => context,
49
50 ServiceError::AlreadyRunning { context, .. } => context,
51
52 ServiceError::NotRunning { context, .. } => context,
53
54 ServiceError::StartFailed { context, .. } => context,
55
56 ServiceError::StopFailed { context, .. } => context,
57
58 ServiceError::Timeout { context, .. } => context,
59
60 ServiceError::DependencyError { context, .. } => context,
61 }
62 }
63
64 pub fn service_not_found(service_name:impl Into<String>) -> Self {
66 let service_name_str = service_name.into();
67
68 Self::ServiceNotFound {
69 context:ErrorContext::new(format!("Service not found: {}", service_name_str))
70 .with_kind(ErrorKind::Service)
71 .with_severity(ErrorSeverity::Error),
72
73 service_name:service_name_str,
74 }
75 }
76
77 pub fn initialization_failed(service_name:impl Into<String>, source:Option<String>) -> Self {
79 let service_name_str = service_name.into();
80
81 Self::InitializationFailed {
82 context:ErrorContext::new(format!("Service initialization failed: {}", service_name_str))
83 .with_kind(ErrorKind::Service)
84 .with_severity(ErrorSeverity::Critical),
85
86 service_name:service_name_str,
87
88 source,
89 }
90 }
91
92 pub fn already_running(service_name:impl Into<String>) -> Self {
94 let service_name_str = service_name.into();
95
96 Self::AlreadyRunning {
97 context:ErrorContext::new(format!("Service already running: {}", service_name_str))
98 .with_kind(ErrorKind::Service)
99 .with_severity(ErrorSeverity::Warning),
100
101 service_name:service_name_str,
102 }
103 }
104
105 pub fn not_running(service_name:impl Into<String>) -> Self {
107 let service_name_str = service_name.into();
108
109 Self::NotRunning {
110 context:ErrorContext::new(format!("Service not running: {}", service_name_str))
111 .with_kind(ErrorKind::Service)
112 .with_severity(ErrorSeverity::Error),
113
114 service_name:service_name_str,
115 }
116 }
117
118 pub fn start_failed(service_name:impl Into<String>, source:Option<String>) -> Self {
120 let service_name_str = service_name.into();
121
122 Self::StartFailed {
123 context:ErrorContext::new(format!("Service start failed: {}", service_name_str))
124 .with_kind(ErrorKind::Service)
125 .with_severity(ErrorSeverity::Error),
126
127 service_name:service_name_str,
128
129 source,
130 }
131 }
132
133 pub fn timeout(service_name:impl Into<String>, operation:impl Into<String>, timeout_ms:u64) -> Self {
135 let service_name_str = service_name.into();
136
137 let operation_str = operation.into();
138
139 Self::Timeout {
140 context:ErrorContext::new(format!(
141 "Service timeout: {} operation timed out after {}ms",
142 service_name_str, timeout_ms
143 ))
144 .with_kind(ErrorKind::Service)
145 .with_severity(ErrorSeverity::Error)
146 .with_operation(operation_str.clone()),
147
148 service_name:service_name_str,
149
150 operation:operation_str,
151
152 timeout_ms,
153 }
154 }
155
156 pub fn dependency_error(service_name:impl Into<String>, dependency:impl Into<String>) -> Self {
158 let service_name_str = service_name.into();
159
160 let dependency_str = dependency.into();
161
162 Self::DependencyError {
163 context:ErrorContext::new(format!(
164 "Service dependency error: {} depends on {}",
165 service_name_str, dependency_str
166 ))
167 .with_kind(ErrorKind::Service)
168 .with_severity(ErrorSeverity::Critical),
169
170 service_name:service_name_str,
171
172 dependency:dependency_str,
173 }
174 }
175}
176
177impl fmt::Display for ServiceError {
178 fn fmt(&self, f:&mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{}", self.context()) }
179}
180
181impl StdError for ServiceError {}
182
183impl From<ServiceError> for MountainError {
184 fn from(err:ServiceError) -> Self { MountainError::new(err.context().clone()).with_source(err.to_string()) }
185}