Mountain/Error/
ServiceError.rs

1//! # Service Error Types
2//!
3//! Provides service-related error types for Mountain.
4//! Used for all service operation errors.
5
6use std::{error::Error as StdError, fmt};
7
8use serde::{Deserialize, Serialize};
9
10use super::CoreError::{ErrorContext, ErrorKind, ErrorSeverity, MountainError, Result};
11
12/// Service operation error types
13#[derive(Debug, Clone, Serialize, Deserialize)]
14pub enum ServiceError {
15	/// Service not found
16	ServiceNotFound { context:ErrorContext, service_name:String },
17	/// Service initialization failed
18	InitializationFailed { context:ErrorContext, service_name:String, source:Option<String> },
19	/// Service already running
20	AlreadyRunning { context:ErrorContext, service_name:String },
21	/// Service not running
22	NotRunning { context:ErrorContext, service_name:String },
23	/// Service start failed
24	StartFailed { context:ErrorContext, service_name:String, source:Option<String> },
25	/// Service stop failed
26	StopFailed { context:ErrorContext, service_name:String, source:Option<String> },
27	/// Service timeout
28	Timeout { context:ErrorContext, service_name:String, operation:String, timeout_ms:u64 },
29	/// Service dependency error
30	DependencyError { context:ErrorContext, service_name:String, dependency:String },
31}
32
33impl ServiceError {
34	/// Get the error context
35	pub fn context(&self) -> &ErrorContext {
36		match self {
37			ServiceError::ServiceNotFound { context, .. } => context,
38			ServiceError::InitializationFailed { context, .. } => context,
39			ServiceError::AlreadyRunning { context, .. } => context,
40			ServiceError::NotRunning { context, .. } => context,
41			ServiceError::StartFailed { context, .. } => context,
42			ServiceError::StopFailed { context, .. } => context,
43			ServiceError::Timeout { context, .. } => context,
44			ServiceError::DependencyError { context, .. } => context,
45		}
46	}
47
48	/// Create a service not found error
49	pub fn service_not_found(service_name:impl Into<String>) -> Self {
50		let service_name_str = service_name.into();
51		Self::ServiceNotFound {
52			context:ErrorContext::new(format!("Service not found: {}", service_name_str))
53				.with_kind(ErrorKind::Service)
54				.with_severity(ErrorSeverity::Error),
55			service_name:service_name_str,
56		}
57	}
58
59	/// Create an initialization failed error
60	pub fn initialization_failed(service_name:impl Into<String>, source:Option<String>) -> Self {
61		let service_name_str = service_name.into();
62		Self::InitializationFailed {
63			context:ErrorContext::new(format!("Service initialization failed: {}", service_name_str))
64				.with_kind(ErrorKind::Service)
65				.with_severity(ErrorSeverity::Critical),
66			service_name:service_name_str,
67			source,
68		}
69	}
70
71	/// Create an already running error
72	pub fn already_running(service_name:impl Into<String>) -> Self {
73		let service_name_str = service_name.into();
74		Self::AlreadyRunning {
75			context:ErrorContext::new(format!("Service already running: {}", service_name_str))
76				.with_kind(ErrorKind::Service)
77				.with_severity(ErrorSeverity::Warning),
78			service_name:service_name_str,
79		}
80	}
81
82	/// Create a not running error
83	pub fn not_running(service_name:impl Into<String>) -> Self {
84		let service_name_str = service_name.into();
85		Self::NotRunning {
86			context:ErrorContext::new(format!("Service not running: {}", service_name_str))
87				.with_kind(ErrorKind::Service)
88				.with_severity(ErrorSeverity::Error),
89			service_name:service_name_str,
90		}
91	}
92
93	/// Create a start failed error
94	pub fn start_failed(service_name:impl Into<String>, source:Option<String>) -> Self {
95		let service_name_str = service_name.into();
96		Self::StartFailed {
97			context:ErrorContext::new(format!("Service start failed: {}", service_name_str))
98				.with_kind(ErrorKind::Service)
99				.with_severity(ErrorSeverity::Error),
100			service_name:service_name_str,
101			source,
102		}
103	}
104
105	/// Create a timeout error
106	pub fn timeout(service_name:impl Into<String>, operation:impl Into<String>, timeout_ms:u64) -> Self {
107		let service_name_str = service_name.into();
108		let operation_str = operation.into();
109		Self::Timeout {
110			context:ErrorContext::new(format!(
111				"Service timeout: {} operation timed out after {}ms",
112				service_name_str, timeout_ms
113			))
114			.with_kind(ErrorKind::Service)
115			.with_severity(ErrorSeverity::Error)
116			.with_operation(operation_str.clone()),
117			service_name:service_name_str,
118			operation:operation_str,
119			timeout_ms,
120		}
121	}
122
123	/// Create a dependency error
124	pub fn dependency_error(service_name:impl Into<String>, dependency:impl Into<String>) -> Self {
125		let service_name_str = service_name.into();
126		let dependency_str = dependency.into();
127		Self::DependencyError {
128			context:ErrorContext::new(format!(
129				"Service dependency error: {} depends on {}",
130				service_name_str, dependency_str
131			))
132			.with_kind(ErrorKind::Service)
133			.with_severity(ErrorSeverity::Critical),
134			service_name:service_name_str,
135			dependency:dependency_str,
136		}
137	}
138}
139
140impl fmt::Display for ServiceError {
141	fn fmt(&self, f:&mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{}", self.context()) }
142}
143
144impl StdError for ServiceError {}
145
146impl From<ServiceError> for MountainError {
147	fn from(err:ServiceError) -> Self { MountainError::new(err.context().clone()).with_source(err.to_string()) }
148}