Skip to main content

actr_cli/core/components/
mod.rs

1//! Core reusable component definitions
2//!
3//! Defines trait interfaces for 8 core components, supporting dependency injection and composition
4
5pub mod cache_manager;
6pub mod config_manager;
7pub mod dependency_resolver;
8pub mod fingerprint_validator;
9pub mod network_validator;
10pub mod proto_processor;
11pub mod service_discovery;
12pub mod user_interface;
13use actr_protocol::{ActrType, discovery_response::TypeEntry};
14pub use cache_manager::DefaultCacheManager;
15pub use config_manager::TomlConfigManager;
16pub use dependency_resolver::DefaultDependencyResolver;
17pub use fingerprint_validator::DefaultFingerprintValidator;
18pub use network_validator::DefaultNetworkValidator;
19pub use proto_processor::DefaultProtoProcessor;
20pub use service_discovery::{DiscoveryContext, NetworkServiceDiscovery};
21pub use user_interface::ConsoleUI;
22
23use actr_config::ManifestConfig;
24use anyhow::Result;
25use async_trait::async_trait;
26use serde::{Deserialize, Serialize};
27use std::path::{Path, PathBuf};
28use std::time::Duration;
29
30// ============================================================================
31// Core data types
32// ============================================================================
33
34/// Dependency specification
35#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
36pub struct DependencySpec {
37    pub alias: String,
38    pub name: String,
39    pub actr_type: Option<ActrType>,
40    pub fingerprint: Option<String>,
41}
42
43/// Resolved dependency information
44#[derive(Debug, Clone)]
45pub struct ResolvedDependency {
46    pub spec: DependencySpec,
47    pub fingerprint: String,
48    pub proto_files: Vec<ProtoFile>,
49}
50
51/// Proto file information
52#[derive(Debug, Clone)]
53pub struct ProtoFile {
54    pub name: String,
55    pub path: PathBuf,
56    pub content: String,
57    pub services: Vec<ServiceDefinition>,
58}
59
60/// Service definition
61#[derive(Debug, Clone)]
62pub struct ServiceDefinition {
63    pub name: String,
64    pub methods: Vec<MethodDefinition>,
65}
66
67/// Method definition
68#[derive(Debug, Clone)]
69pub struct MethodDefinition {
70    pub name: String,
71    pub input_type: String,
72    pub output_type: String,
73}
74
75/// Service information
76#[derive(Debug, Clone)]
77pub struct ServiceInfo {
78    /// Service name (package name)
79    pub name: String,
80    pub tags: Vec<String>,
81    pub fingerprint: String,
82    pub actr_type: ActrType,
83    pub published_at: Option<i64>,
84    pub description: Option<String>,
85    pub methods: Vec<MethodDefinition>,
86}
87
88/// Service details
89#[derive(Debug, Clone)]
90pub struct ServiceDetails {
91    pub info: ServiceInfo,
92    pub proto_files: Vec<ProtoFile>,
93    pub dependencies: Vec<String>,
94}
95
96/// Fingerprint information
97#[derive(Debug, Clone, PartialEq)]
98pub struct Fingerprint {
99    pub algorithm: String,
100    pub value: String,
101}
102
103/// Validation report
104#[derive(Debug, Clone)]
105pub struct ValidationReport {
106    pub is_valid: bool,
107    pub config_validation: ConfigValidation,
108    pub dependency_validation: Vec<DependencyValidation>,
109    pub network_validation: Vec<NetworkValidation>,
110    pub fingerprint_validation: Vec<FingerprintValidation>,
111    pub conflicts: Vec<ConflictReport>,
112}
113
114#[derive(Debug, Clone)]
115pub struct ConfigValidation {
116    pub is_valid: bool,
117    pub errors: Vec<String>,
118    pub warnings: Vec<String>,
119}
120
121#[derive(Debug, Clone)]
122pub struct DependencyValidation {
123    pub dependency: String,
124    pub is_available: bool,
125    pub error: Option<String>,
126}
127
128#[derive(Debug, Clone)]
129pub struct NetworkValidation {
130    pub is_reachable: bool,
131    pub health: HealthStatus,
132    pub latency_ms: Option<u64>,
133    pub error: Option<String>,
134    pub is_applicable: bool,
135}
136
137#[derive(Debug, Clone)]
138pub struct FingerprintValidation {
139    pub dependency: String,
140    pub expected: Fingerprint,
141    pub actual: Option<Fingerprint>,
142    pub is_valid: bool,
143    pub error: Option<String>,
144}
145
146#[derive(Debug, Clone)]
147pub struct ConflictReport {
148    pub dependency_a: String,
149    pub dependency_b: String,
150    pub conflict_type: ConflictType,
151    pub description: String,
152}
153
154#[derive(Debug, Clone)]
155pub enum ConflictType {
156    VersionConflict,
157    FingerprintMismatch,
158    CircularDependency,
159}
160
161impl ValidationReport {
162    pub fn is_success(&self) -> bool {
163        self.is_valid
164            && self.config_validation.is_valid
165            && self.dependency_validation.iter().all(|d| d.is_available)
166            && self
167                .network_validation
168                .iter()
169                .all(|n| !n.is_applicable || n.is_reachable)
170            && self.fingerprint_validation.iter().all(|f| f.is_valid)
171            && self.conflicts.is_empty()
172    }
173}
174
175// ============================================================================
176// 1. Configuration Management Component (ConfigManager)
177// ============================================================================
178
179/// Unified configuration management interface
180#[async_trait]
181pub trait ConfigManager: Send + Sync {
182    /// Load configuration file
183    async fn load_config(&self, path: &Path) -> Result<ManifestConfig>;
184
185    /// Save configuration file
186    async fn save_config(&self, config: &ManifestConfig, path: &Path) -> Result<()>;
187
188    /// Update dependency configuration
189    async fn update_dependency(&self, spec: &DependencySpec) -> Result<()>;
190
191    /// Validate configuration file
192    async fn validate_config(&self) -> Result<ConfigValidation>;
193
194    /// Get project root directory
195    fn get_project_root(&self) -> &Path;
196
197    /// Back up current configuration
198    async fn backup_config(&self) -> Result<ConfigBackup>;
199
200    /// Restore configuration backup
201    async fn restore_backup(&self, backup: ConfigBackup) -> Result<()>;
202
203    /// Remove configuration backup
204    async fn remove_backup(&self, backup: ConfigBackup) -> Result<()>;
205}
206
207#[derive(Debug, Clone, Serialize, Deserialize)]
208pub struct PackageConfig {
209    pub name: String,
210    pub version: String,
211    #[serde(rename = "type")]
212    pub package_type: Option<String>,
213}
214
215/// Configuration backup
216#[derive(Debug, Clone)]
217pub struct ConfigBackup {
218    pub original_path: PathBuf,
219    pub backup_path: PathBuf,
220    pub timestamp: std::time::SystemTime,
221}
222
223// ============================================================================
224// 2. Dependency Resolver Component (DependencyResolver)
225// ============================================================================
226
227/// Dependency resolution and conflict detection
228#[async_trait]
229pub trait DependencyResolver: Send + Sync {
230    /// Parse dependencies from config
231    async fn resolve_spec(&self, config: &ManifestConfig) -> Result<Vec<DependencySpec>>;
232
233    /// Resolve dependencies and fetch proto files
234    async fn resolve_dependencies(
235        &self,
236        specs: &[DependencySpec],
237        service_details: &[ServiceDetails],
238    ) -> Result<Vec<ResolvedDependency>>;
239
240    /// Check dependency conflicts
241    async fn check_conflicts(&self, deps: &[ResolvedDependency]) -> Result<Vec<ConflictReport>>;
242
243    /// Build dependency graph
244    async fn build_dependency_graph(&self, deps: &[ResolvedDependency]) -> Result<DependencyGraph>;
245}
246
247#[derive(Debug, Clone)]
248pub struct DependencyGraph {
249    pub nodes: Vec<String>,
250    pub edges: Vec<(String, String)>,
251    pub has_cycles: bool,
252}
253
254// ============================================================================
255// 3. Service Discovery Component (ServiceDiscovery)
256// ============================================================================
257
258/// Service discovery and network interaction
259#[async_trait]
260pub trait ServiceDiscovery: Send + Sync {
261    /// Discover services in the network
262    async fn discover_services(&self, filter: Option<&ServiceFilter>) -> Result<Vec<ServiceInfo>>;
263
264    /// Get detailed service information
265    async fn get_service_details(&self, name: &str) -> Result<ServiceDetails>;
266
267    /// Check service availability
268    async fn check_service_availability(&self, name: &str) -> Result<AvailabilityStatus>;
269
270    /// Get service proto files
271    async fn get_service_proto(&self, name: &str) -> Result<Vec<ProtoFile>>;
272}
273
274#[derive(Debug, Clone)]
275pub struct ServiceFilter {
276    pub name_pattern: Option<String>,
277    pub version_range: Option<String>,
278    pub tags: Option<Vec<String>>,
279}
280
281#[derive(Debug, Clone)]
282pub struct AvailabilityStatus {
283    pub is_available: bool,
284    pub last_seen: Option<std::time::SystemTime>,
285    pub health: HealthStatus,
286}
287
288#[derive(Debug, Clone)]
289pub enum HealthStatus {
290    Healthy,
291    Degraded,
292    Unhealthy,
293    Unknown,
294}
295
296// ============================================================================
297// 4. Network Validator Component (NetworkValidator)
298// ============================================================================
299
300/// Network connectivity validation
301#[async_trait]
302pub trait NetworkValidator: Send + Sync {
303    /// Check connectivity
304    async fn check_connectivity(
305        &self,
306        service_name: &str,
307        options: &NetworkCheckOptions,
308    ) -> Result<ConnectivityStatus>;
309
310    /// Verify service health status
311    async fn verify_service_health(
312        &self,
313        service_name: &str,
314        options: &NetworkCheckOptions,
315    ) -> Result<HealthStatus>;
316
317    /// Test latency
318    async fn test_latency(
319        &self,
320        service_name: &str,
321        options: &NetworkCheckOptions,
322    ) -> Result<LatencyInfo>;
323
324    /// Batch check
325    async fn batch_check(
326        &self,
327        service_names: &[String],
328        options: &NetworkCheckOptions,
329    ) -> Result<Vec<NetworkCheckResult>>;
330}
331
332#[derive(Debug, Clone)]
333pub struct ConnectivityStatus {
334    pub is_reachable: bool,
335    pub response_time_ms: Option<u64>,
336    pub error: Option<String>,
337}
338
339#[derive(Debug, Clone)]
340pub struct LatencyInfo {
341    pub min_ms: u64,
342    pub max_ms: u64,
343    pub avg_ms: u64,
344    pub samples: u32,
345}
346
347#[derive(Debug, Clone)]
348pub struct NetworkCheckResult {
349    pub connectivity: ConnectivityStatus,
350    pub health: HealthStatus,
351    pub latency: Option<LatencyInfo>,
352}
353
354/// Options for network checks.
355#[derive(Debug, Clone)]
356pub struct NetworkCheckOptions {
357    pub timeout: Duration,
358}
359
360impl NetworkCheckOptions {
361    pub fn with_timeout(timeout: Duration) -> Self {
362        Self { timeout }
363    }
364
365    pub fn with_timeout_secs(timeout_secs: u64) -> Self {
366        Self::with_timeout(Duration::from_secs(timeout_secs))
367    }
368}
369
370impl Default for NetworkCheckOptions {
371    fn default() -> Self {
372        Self {
373            timeout: Duration::from_secs(5),
374        }
375    }
376}
377
378// ============================================================================
379// 5. Fingerprint Validator Component (FingerprintValidator)
380// ============================================================================
381
382/// Fingerprint computation and validation
383#[async_trait]
384pub trait FingerprintValidator: Send + Sync {
385    /// Compute service fingerprint
386    async fn compute_service_fingerprint(&self, service: &ServiceInfo) -> Result<Fingerprint>;
387
388    /// Verify fingerprint match
389    async fn verify_fingerprint(
390        &self,
391        expected: &Fingerprint,
392        actual: &Fingerprint,
393    ) -> Result<bool>;
394
395    /// Compute project fingerprint
396    async fn compute_project_fingerprint(&self, project_path: &Path) -> Result<Fingerprint>;
397
398    /// Generate lock file fingerprint
399    async fn generate_lock_fingerprint(&self, deps: &[ResolvedDependency]) -> Result<Fingerprint>;
400}
401
402// ============================================================================
403// 6. Proto Processor Component (ProtoProcessor)
404// ============================================================================
405
406/// Protocol Buffers file processing
407#[async_trait]
408pub trait ProtoProcessor: Send + Sync {
409    /// Discover proto files
410    async fn discover_proto_files(&self, path: &Path) -> Result<Vec<ProtoFile>>;
411
412    /// Parse proto services
413    async fn parse_proto_services(&self, files: &[ProtoFile]) -> Result<Vec<ServiceDefinition>>;
414
415    /// Generate code
416    async fn generate_code(&self, input: &Path, output: &Path) -> Result<GenerationResult>;
417
418    /// Validate proto syntax
419    async fn validate_proto_syntax(&self, files: &[ProtoFile]) -> Result<ValidationReport>;
420}
421
422#[derive(Debug, Clone)]
423pub struct GenerationResult {
424    pub generated_files: Vec<PathBuf>,
425    pub warnings: Vec<String>,
426    pub errors: Vec<String>,
427}
428
429// ============================================================================
430// 7. Cache Manager Component (CacheManager)
431// ============================================================================
432
433/// Dependency cache management
434#[async_trait]
435pub trait CacheManager: Send + Sync {
436    /// Get cached proto
437    async fn get_cached_proto(&self, service_name: &str) -> Result<Option<CachedProto>>;
438
439    /// Cache proto files
440    async fn cache_proto(&self, service_name: &str, proto: &[ProtoFile]) -> Result<()>;
441
442    /// Invalidate cache
443    async fn invalidate_cache(&self, service_name: &str) -> Result<()>;
444
445    /// Clear cache
446    async fn clear_cache(&self) -> Result<()>;
447
448    /// Get cache statistics
449    async fn get_cache_stats(&self) -> Result<CacheStats>;
450}
451
452#[derive(Debug, Clone)]
453pub struct CachedProto {
454    pub files: Vec<ProtoFile>,
455    pub fingerprint: Fingerprint,
456    pub cached_at: std::time::SystemTime,
457    pub expires_at: Option<std::time::SystemTime>,
458}
459
460#[derive(Debug, Clone)]
461pub struct CacheStats {
462    pub total_entries: usize,
463    pub total_size_bytes: u64,
464    pub hit_rate: f64,
465    pub miss_rate: f64,
466}
467
468// ============================================================================
469// 8. User Interface Component (UserInterface)
470// ============================================================================
471
472/// User interaction interface
473#[async_trait]
474pub trait UserInterface: Send + Sync {
475    /// Prompt for input
476    async fn prompt_input(&self, prompt: &str) -> Result<String>;
477
478    /// Confirm an operation
479    async fn confirm(&self, message: &str) -> Result<bool>;
480
481    /// Select one item from a list
482    async fn select_from_list(&self, items: &[String], prompt: &str) -> Result<usize>;
483
484    /// Display a service table
485    async fn display_service_table(
486        &self,
487        items: &[ServiceInfo],
488        headers: &[&str],
489        formatter: fn(&ServiceInfo) -> Vec<String>,
490    );
491
492    /// Show a progress bar
493    async fn show_progress(&self, message: &str) -> Result<Box<dyn ProgressBar>>;
494}
495
496/// Progress bar interface
497pub trait ProgressBar: Send + Sync {
498    fn update(&self, progress: f64);
499    fn set_message(&self, message: &str);
500    fn finish(&self);
501}
502
503impl From<TypeEntry> for ServiceInfo {
504    fn from(entry: TypeEntry) -> Self {
505        let name = entry.name.clone();
506        let tags = entry.tags.clone();
507        let actr_type = entry.actr_type.clone();
508
509        Self {
510            name,
511            actr_type,
512            tags,
513            published_at: entry.published_at,
514            fingerprint: entry.service_fingerprint,
515            description: entry.description,
516            methods: Vec::new(),
517        }
518    }
519}