|
11 | 11 | //! - Manual configuration correction (advanced users) |
12 | 12 | //! - Review trace file for detailed error information |
13 | 13 |
|
| 14 | +use std::path::PathBuf; |
| 15 | +use std::time::Duration; |
| 16 | + |
| 17 | +use chrono::{DateTime, Utc}; |
14 | 18 | use serde::{Deserialize, Serialize}; |
15 | 19 |
|
16 | | -use crate::domain::environment::state::{ |
17 | | - AnyEnvironmentState, ConfigureFailureContext, StateTypeError, |
18 | | -}; |
19 | | -use crate::domain::environment::Environment; |
| 20 | +use crate::domain::environment::state::{AnyEnvironmentState, StateTypeError}; |
| 21 | +use crate::domain::environment::{Environment, TraceId}; |
| 22 | + |
| 23 | +// ============================================================================ |
| 24 | +// Configure Command Error Context |
| 25 | +// ============================================================================ |
| 26 | + |
| 27 | +/// Error context for configure command failures |
| 28 | +/// |
| 29 | +/// Captures comprehensive information about configuration failures including |
| 30 | +/// the specific step that failed, error classification, timing, and trace details. |
| 31 | +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] |
| 32 | +pub struct ConfigureFailureContext { |
| 33 | + /// Which step failed during configuration |
| 34 | + pub failed_step: ConfigureStep, |
| 35 | + |
| 36 | + /// Error category for type-safe handling |
| 37 | + pub error_kind: ConfigureErrorKind, |
| 38 | + |
| 39 | + /// Human-readable error summary |
| 40 | + pub error_summary: String, |
| 41 | + |
| 42 | + /// When the failure occurred |
| 43 | + pub failed_at: DateTime<Utc>, |
| 44 | + |
| 45 | + /// When execution started |
| 46 | + pub execution_started_at: DateTime<Utc>, |
| 47 | + |
| 48 | + /// How long execution ran before failing |
| 49 | + pub execution_duration: Duration, |
| 50 | + |
| 51 | + /// Unique trace identifier |
| 52 | + pub trace_id: TraceId, |
| 53 | + |
| 54 | + /// Path to the detailed trace file (if generated) |
| 55 | + pub trace_file_path: Option<PathBuf>, |
| 56 | +} |
| 57 | + |
| 58 | +/// Steps in the configure workflow |
| 59 | +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] |
| 60 | +pub enum ConfigureStep { |
| 61 | + /// Installing Docker |
| 62 | + InstallDocker, |
| 63 | + /// Installing Docker Compose |
| 64 | + InstallDockerCompose, |
| 65 | +} |
| 66 | + |
| 67 | +/// Error categories for configure failures |
| 68 | +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] |
| 69 | +pub enum ConfigureErrorKind { |
| 70 | + /// Software installation failed |
| 71 | + InstallationFailed, |
| 72 | + /// Command execution failed |
| 73 | + CommandExecutionFailed, |
| 74 | +} |
20 | 75 |
|
21 | 76 | /// Error state - Application configuration failed |
22 | 77 | /// |
@@ -64,12 +119,6 @@ impl AnyEnvironmentState { |
64 | 119 | #[cfg(test)] |
65 | 120 | mod tests { |
66 | 121 | use super::*; |
67 | | - use crate::domain::environment::state::{ |
68 | | - ConfigureErrorKind, ConfigureFailureContext, ConfigureStep, |
69 | | - }; |
70 | | - use crate::domain::environment::TraceId; |
71 | | - use chrono::Utc; |
72 | | - use std::time::Duration; |
73 | 122 |
|
74 | 123 | fn create_test_context() -> ConfigureFailureContext { |
75 | 124 | ConfigureFailureContext { |
@@ -161,4 +210,50 @@ mod tests { |
161 | 210 | assert!(result.is_ok()); |
162 | 211 | } |
163 | 212 | } |
| 213 | + |
| 214 | + mod context_tests { |
| 215 | + use super::*; |
| 216 | + |
| 217 | + #[test] |
| 218 | + fn it_should_serialize_configure_failure_context() { |
| 219 | + let context = ConfigureFailureContext { |
| 220 | + failed_step: ConfigureStep::InstallDocker, |
| 221 | + error_kind: ConfigureErrorKind::InstallationFailed, |
| 222 | + error_summary: "Docker installation failed".to_string(), |
| 223 | + failed_at: Utc::now(), |
| 224 | + execution_started_at: Utc::now(), |
| 225 | + execution_duration: Duration::from_secs(15), |
| 226 | + trace_id: TraceId::new(), |
| 227 | + trace_file_path: None, |
| 228 | + }; |
| 229 | + |
| 230 | + let json = serde_json::to_string(&context).unwrap(); |
| 231 | + assert!(json.contains("InstallDocker")); |
| 232 | + assert!(json.contains("InstallationFailed")); |
| 233 | + } |
| 234 | + |
| 235 | + #[test] |
| 236 | + fn it_should_deserialize_configure_failure_context() { |
| 237 | + let trace_id = TraceId::new(); |
| 238 | + let json = format!( |
| 239 | + r#"{{ |
| 240 | + "failed_step": "InstallDockerCompose", |
| 241 | + "error_kind": "CommandExecutionFailed", |
| 242 | + "error_summary": "Command execution failed", |
| 243 | + "failed_at": "2025-10-06T10:00:00Z", |
| 244 | + "execution_started_at": "2025-10-06T09:59:30Z", |
| 245 | + "execution_duration": {{"secs": 30, "nanos": 0}}, |
| 246 | + "trace_id": "{trace_id}", |
| 247 | + "trace_file_path": null |
| 248 | + }}"# |
| 249 | + ); |
| 250 | + |
| 251 | + let context: ConfigureFailureContext = serde_json::from_str(&json).unwrap(); |
| 252 | + assert_eq!(context.failed_step, ConfigureStep::InstallDockerCompose); |
| 253 | + assert_eq!( |
| 254 | + context.error_kind, |
| 255 | + ConfigureErrorKind::CommandExecutionFailed |
| 256 | + ); |
| 257 | + } |
| 258 | + } |
164 | 259 | } |
0 commit comments