-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathmod.rs
More file actions
131 lines (128 loc) · 5.01 KB
/
Copy pathmod.rs
File metadata and controls
131 lines (128 loc) · 5.01 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
//! Dispatch Layer - Presentation Layer Component
//!
//! The Dispatch Layer is responsible for routing parsed commands to their appropriate handlers
//! and providing execution context for command processing. This is the second layer in the
//! presentation layer's four-layer architecture: Input → Dispatch → Controllers → Views.
//!
//! ## Purpose
//!
//! The Dispatch Layer establishes clear separation between:
//! - **Command routing** (determining which handler to execute)
//! - **Execution context** (providing dependencies to handlers)
//! - **Command execution** (actual command logic in Controllers layer)
//! - **Result presentation** (handled by Views layer)
//!
//! This separation provides several benefits:
//! - **Single Responsibility**: Routing logic isolated from command execution
//! - **Testability**: Router can be tested independently of command handlers
//! - **Dependency Injection**: Clean pattern for providing services to commands
//! - **Scalability**: Easy to add new commands without modifying existing handlers
//!
//! ## Module Structure
//!
//! ```text
//! dispatch/
//! ├── mod.rs # This file - layer exports and documentation
//! ├── router.rs # Command routing logic (route_command function)
//! └── context.rs # ExecutionContext wrapper around Container
//! ```
//!
//! ## `ExecutionContext` Design
//!
//! The Dispatch Layer uses an `ExecutionContext` wrapper around the `Container` rather than
//! passing the `Container` directly to command handlers. This design choice provides several
//! important benefits:
//!
//! ### 1. Future-Proof Command Signatures
//!
//! By using `ExecutionContext`, we can extend execution context in the future without
//! breaking existing command handler signatures:
//!
//! ```rust,ignore
//! use std::sync::Arc;
//! use torrust_tracker_deployer_lib::bootstrap::Container;
//!
//! pub struct ExecutionContext {
//! container: Arc<Container>,
//! // Future additions without breaking changes:
//! // request_id: RequestId,
//! // execution_metadata: ExecutionMetadata,
//! // tracing_context: TracingContext,
//! // user_permissions: UserPermissions,
//! }
//! ```
//!
//! ### 2. Clear Abstraction and Intent
//!
//! `ExecutionContext` represents "everything a command needs to execute" rather than
//! exposing dependency injection mechanics directly:
//!
//! ```rust,no_run
//! use torrust_tracker_deployer_lib::bootstrap::Container;
//! use torrust_tracker_deployer_lib::presentation::cli::dispatch::ExecutionContext;
//!
//! # fn example() {
//! // Clear: This is specifically for command execution
//! fn handle_command(context: &ExecutionContext) {
//! // Command execution logic
//! }
//!
//! // Less clear: Could be for bootstrapping, testing, or execution
//! fn handle_command_old(container: &Container) {
//! // Generic container usage
//! }
//! # }
//! ```
//!
//! ### 3. Command-Specific Service Access
//!
//! `ExecutionContext` can provide command-specific convenience methods and service
//! aggregations without exposing the entire Container interface.
//!
//! For the complete rationale, see the architectural decision record:
//! [`docs/decisions/execution-context-wrapper.md`](../../../docs/decisions/execution-context-wrapper.md)
//!
//! ## Design Principles
//!
//! - **Route, Don't Execute**: This layer only routes commands, doesn't execute them
//! - **Dependency Injection**: Provide clean access to services via `ExecutionContext`
//! - **Type Safety**: Use strongly-typed routing with match statements
//! - **Error Propagation**: Pass routing errors up to caller
//!
//! ## Integration with Presentation Layer
//!
//! The Dispatch Layer integrates with the broader presentation layer architecture:
//!
//! 1. **Input Layer** (`input/`) - Parses user input into Commands enum
//! 2. **Dispatch Layer** (this module) - Routes commands and provides context
//! 3. **Controller Layer** (`commands/`) - Executes command logic with context
//! 4. **View Layer** (`user_output/`, `progress.rs`) - Presents results to users
//!
//! ## Usage Pattern
//!
//! ```rust,ignore
//! use std::path::Path;
//! use std::sync::Arc;
//! use torrust_tracker_deployer_lib::bootstrap::Container;
//! use torrust_tracker_deployer_lib::presentation::cli::dispatch::{route_command, ExecutionContext};
//! use torrust_tracker_deployer_lib::presentation::cli::views::VerbosityLevel;
//! // Note: Commands enum requires specific action parameters in practice
//!
//! # fn example() -> Result<(), Box<dyn std::error::Error>> {
//! let container = Container::new(VerbosityLevel::Normal);
//! let context = ExecutionContext::new(Arc::new(container), global_args);
//! let working_dir = Path::new(".");
//!
//! // Execute a command through the dispatch layer
//! // Note: route_command is synchronous, not async
//! // Commands require proper construction with actions
//! # Ok(())
//! # }
//! ```
// Command routing module
pub mod router;
// Execution context module
pub mod context;
// Re-export main types for convenience
pub use context::ExecutionContext;
pub use router::route_command;