actr_cli/core/
pipelines.rs

1//! 操作管道定义
2//!
3//! 定义了三个核心操作管道,实现命令间的逻辑复用
4
5use anyhow::Result;
6use std::sync::Arc;
7
8use super::components::*;
9
10// ============================================================================
11// 管道结果类型
12// ============================================================================
13
14/// 安装结果
15#[derive(Debug, Clone)]
16pub struct InstallResult {
17    pub installed_dependencies: Vec<ResolvedDependency>,
18    pub updated_config: bool,
19    pub updated_lock_file: bool,
20    pub cache_updates: usize,
21    pub warnings: Vec<String>,
22}
23
24impl InstallResult {
25    pub fn success() -> Self {
26        Self {
27            installed_dependencies: Vec::new(),
28            updated_config: false,
29            updated_lock_file: false,
30            cache_updates: 0,
31            warnings: Vec::new(),
32        }
33    }
34
35    pub fn summary(&self) -> String {
36        format!(
37            "安装了 {} 个依赖,更新了 {} 个缓存项",
38            self.installed_dependencies.len(),
39            self.cache_updates
40        )
41    }
42}
43
44/// 安装计划
45#[derive(Debug, Clone)]
46pub struct InstallPlan {
47    pub dependencies_to_install: Vec<DependencySpec>,
48    pub resolved_dependencies: Vec<ResolvedDependency>,
49    pub estimated_cache_size: u64,
50    pub required_permissions: Vec<String>,
51}
52
53/// 生成选项
54#[derive(Debug, Clone)]
55pub struct GenerationOptions {
56    pub input_path: std::path::PathBuf,
57    pub output_path: std::path::PathBuf,
58    pub clean_before_generate: bool,
59    pub generate_scaffold: bool,
60    pub format_code: bool,
61    pub run_checks: bool,
62}
63
64// ============================================================================
65// 1. 验证管道 (ValidationPipeline)
66// ============================================================================
67
68/// 核心验证管道 - 被多个命令复用
69#[derive(Clone)]
70pub struct ValidationPipeline {
71    config_manager: Arc<dyn ConfigManager>,
72    dependency_resolver: Arc<dyn DependencyResolver>,
73    service_discovery: Arc<dyn ServiceDiscovery>,
74    network_validator: Arc<dyn NetworkValidator>,
75    fingerprint_validator: Arc<dyn FingerprintValidator>,
76}
77
78impl ValidationPipeline {
79    pub fn new(
80        config_manager: Arc<dyn ConfigManager>,
81        dependency_resolver: Arc<dyn DependencyResolver>,
82        service_discovery: Arc<dyn ServiceDiscovery>,
83        network_validator: Arc<dyn NetworkValidator>,
84        fingerprint_validator: Arc<dyn FingerprintValidator>,
85    ) -> Self {
86        Self {
87            config_manager,
88            dependency_resolver,
89            service_discovery,
90            network_validator,
91            fingerprint_validator,
92        }
93    }
94
95    /// 完整的项目验证流程
96    pub async fn validate_project(&self) -> Result<ValidationReport> {
97        // 1. 配置文件验证
98        let config_validation = self.config_manager.validate_config().await?;
99
100        // 如果配置文件都有问题,直接返回
101        if !config_validation.is_valid {
102            return Ok(ValidationReport {
103                is_valid: false,
104                config_validation,
105                dependency_validation: vec![],
106                network_validation: vec![],
107                fingerprint_validation: vec![],
108                conflicts: vec![],
109            });
110        }
111
112        // 2. 依赖解析和验证
113        let config = self
114            .config_manager
115            .load_config(
116                self.config_manager
117                    .get_project_root()
118                    .join("Actr.toml")
119                    .as_path(),
120            )
121            .await?;
122        let dependency_specs = self.extract_dependency_specs(&config)?;
123        let resolved_dependencies = self
124            .dependency_resolver
125            .resolve_dependencies(&dependency_specs)
126            .await?;
127
128        // 3. 冲突检查
129        let conflicts = self
130            .dependency_resolver
131            .check_conflicts(&resolved_dependencies)
132            .await?;
133
134        // 4. 串行执行网络验证和指纹验证(简化版,实际可以并行)
135        let dependency_validation = self.validate_dependencies(&dependency_specs).await?;
136        let network_validation = self
137            .validate_network_connectivity(&resolved_dependencies)
138            .await?;
139        let fingerprint_validation = self.validate_fingerprints(&resolved_dependencies).await?;
140
141        let is_valid = config_validation.is_valid
142            && dependency_validation.iter().all(|d| d.is_available)
143            && network_validation.iter().all(|n| n.is_reachable)
144            && fingerprint_validation.iter().all(|f| f.is_valid)
145            && conflicts.is_empty();
146
147        Ok(ValidationReport {
148            is_valid,
149            config_validation,
150            dependency_validation,
151            network_validation,
152            fingerprint_validation,
153            conflicts,
154        })
155    }
156
157    /// 验证特定依赖列表
158    pub async fn validate_dependencies(
159        &self,
160        specs: &[DependencySpec],
161    ) -> Result<Vec<DependencyValidation>> {
162        let mut results = Vec::new();
163
164        for spec in specs {
165            let validation = match self
166                .service_discovery
167                .check_service_availability(&spec.uri)
168                .await
169            {
170                Ok(status) => DependencyValidation {
171                    dependency: spec.name.clone(),
172                    is_available: status.is_available,
173                    resolved_uri: Some(spec.uri.clone()),
174                    error: None,
175                },
176                Err(e) => DependencyValidation {
177                    dependency: spec.name.clone(),
178                    is_available: false,
179                    resolved_uri: None,
180                    error: Some(e.to_string()),
181                },
182            };
183            results.push(validation);
184        }
185
186        Ok(results)
187    }
188
189    /// 网络连通性验证
190    async fn validate_network_connectivity(
191        &self,
192        deps: &[ResolvedDependency],
193    ) -> Result<Vec<NetworkValidation>> {
194        let uris: Vec<String> = deps.iter().map(|d| d.uri.clone()).collect();
195        let network_results = self.network_validator.batch_check(&uris).await?;
196
197        Ok(network_results
198            .into_iter()
199            .map(|result| NetworkValidation {
200                uri: result.uri,
201                is_reachable: result.connectivity.is_reachable,
202                latency_ms: result.connectivity.response_time_ms,
203                error: result.connectivity.error,
204            })
205            .collect())
206    }
207
208    /// 指纹验证
209    async fn validate_fingerprints(
210        &self,
211        deps: &[ResolvedDependency],
212    ) -> Result<Vec<FingerprintValidation>> {
213        let mut results = Vec::new();
214
215        for dep in deps {
216            let expected = Fingerprint {
217                algorithm: "sha256".to_string(),
218                value: dep.fingerprint.clone(),
219            };
220
221            // 计算实际指纹
222            let service_info = match self.service_discovery.get_service_details(&dep.uri).await {
223                Ok(details) => details.info,
224                Err(e) => {
225                    results.push(FingerprintValidation {
226                        dependency: dep.spec.name.clone(),
227                        expected,
228                        actual: None,
229                        is_valid: false,
230                        error: Some(e.to_string()),
231                    });
232                    continue;
233                }
234            };
235
236            match self
237                .fingerprint_validator
238                .compute_service_fingerprint(&service_info)
239                .await
240            {
241                Ok(actual) => {
242                    let is_valid = self
243                        .fingerprint_validator
244                        .verify_fingerprint(&expected, &actual)
245                        .await
246                        .unwrap_or(false);
247                    results.push(FingerprintValidation {
248                        dependency: dep.spec.name.clone(),
249                        expected,
250                        actual: Some(actual),
251                        is_valid,
252                        error: None,
253                    });
254                }
255                Err(e) => {
256                    results.push(FingerprintValidation {
257                        dependency: dep.spec.name.clone(),
258                        expected,
259                        actual: None,
260                        is_valid: false,
261                        error: Some(e.to_string()),
262                    });
263                }
264            }
265        }
266
267        Ok(results)
268    }
269
270    /// 从配置中提取依赖规范
271    fn extract_dependency_specs(&self, config: &ActrConfig) -> Result<Vec<DependencySpec>> {
272        let mut specs = Vec::new();
273
274        if let Some(dependencies) = &config.dependencies {
275            for (name, dep_config) in dependencies {
276                let spec = match dep_config {
277                    DependencyConfig::Simple(uri) => DependencySpec {
278                        name: name.clone(),
279                        uri: uri.clone(),
280                        version: None,
281                        fingerprint: None,
282                    },
283                    DependencyConfig::Complex {
284                        uri,
285                        version,
286                        fingerprint,
287                    } => DependencySpec {
288                        name: name.clone(),
289                        uri: uri.clone(),
290                        version: version.clone(),
291                        fingerprint: fingerprint.clone(),
292                    },
293                };
294                specs.push(spec);
295            }
296        }
297
298        Ok(specs)
299    }
300}
301
302// ============================================================================
303// 2. 安装管道 (InstallPipeline)
304// ============================================================================
305
306/// 安装管道 - 基于ValidationPipeline构建
307pub struct InstallPipeline {
308    validation_pipeline: ValidationPipeline,
309    config_manager: Arc<dyn ConfigManager>,
310    cache_manager: Arc<dyn CacheManager>,
311    #[allow(dead_code)]
312    proto_processor: Arc<dyn ProtoProcessor>,
313}
314
315impl InstallPipeline {
316    pub fn new(
317        validation_pipeline: ValidationPipeline,
318        config_manager: Arc<dyn ConfigManager>,
319        cache_manager: Arc<dyn CacheManager>,
320        proto_processor: Arc<dyn ProtoProcessor>,
321    ) -> Self {
322        Self {
323            validation_pipeline,
324            config_manager,
325            cache_manager,
326            proto_processor,
327        }
328    }
329
330    /// Check-First 安装流程
331    pub async fn install_dependencies(&self, specs: &[DependencySpec]) -> Result<InstallResult> {
332        // 🔍 阶段1: 完整验证 (复用ValidationPipeline)
333        let validation_report = self
334            .validation_pipeline
335            .validate_dependencies(specs)
336            .await?;
337
338        // 检查验证结果
339        let failed_validations: Vec<_> = validation_report
340            .iter()
341            .filter(|v| !v.is_available)
342            .collect();
343
344        if !failed_validations.is_empty() {
345            return Err(anyhow::anyhow!(
346                "依赖验证失败: {}",
347                failed_validations
348                    .iter()
349                    .map(|v| format!(
350                        "{}: {}",
351                        v.dependency,
352                        v.error.as_deref().unwrap_or("unknown error")
353                    ))
354                    .collect::<Vec<_>>()
355                    .join(", ")
356            ));
357        }
358
359        // 📝 阶段2: 原子性安装
360        let backup = self.config_manager.backup_config().await?;
361
362        match self.execute_atomic_install(specs).await {
363            Ok(result) => {
364                // 安装成功,清理备份
365                self.config_manager.remove_backup(backup).await?;
366                Ok(result)
367            }
368            Err(e) => {
369                // 安装失败,恢复备份
370                self.config_manager.restore_backup(backup).await?;
371                Err(e)
372            }
373        }
374    }
375
376    /// 原子性安装执行
377    async fn execute_atomic_install(&self, specs: &[DependencySpec]) -> Result<InstallResult> {
378        let mut result = InstallResult::success();
379
380        for spec in specs {
381            // 1. 更新配置文件
382            self.config_manager.update_dependency(spec).await?;
383            result.updated_config = true;
384
385            // 2. 获取服务详情并缓存Proto文件
386            let service_details = self
387                .validation_pipeline
388                .service_discovery
389                .get_service_details(&spec.uri)
390                .await?;
391
392            self.cache_manager
393                .cache_proto(&spec.uri, &service_details.proto_files)
394                .await?;
395            result.cache_updates += 1;
396
397            // 3. 记录已安装的依赖
398            let resolved_dep = ResolvedDependency {
399                spec: spec.clone(),
400                uri: spec.uri.clone(),
401                resolved_version: service_details.info.version,
402                fingerprint: service_details.info.fingerprint,
403                proto_files: service_details.proto_files,
404            };
405            result.installed_dependencies.push(resolved_dep);
406        }
407
408        // 4. 更新锁文件
409        self.update_lock_file(&result.installed_dependencies)
410            .await?;
411        result.updated_lock_file = true;
412
413        Ok(result)
414    }
415
416    /// 更新锁文件
417    async fn update_lock_file(&self, dependencies: &[ResolvedDependency]) -> Result<()> {
418        // TODO: 实现锁文件更新逻辑
419        // 这里应该读取现有的锁文件,合并新的依赖信息,然后写回
420        println!("更新锁文件: {} 个依赖", dependencies.len());
421        Ok(())
422    }
423}
424
425// ============================================================================
426// 3. 生成管道 (GenerationPipeline)
427// ============================================================================
428
429/// 代码生成管道
430pub struct GenerationPipeline {
431    #[allow(dead_code)]
432    config_manager: Arc<dyn ConfigManager>,
433    proto_processor: Arc<dyn ProtoProcessor>,
434    #[allow(dead_code)]
435    cache_manager: Arc<dyn CacheManager>,
436}
437
438impl GenerationPipeline {
439    pub fn new(
440        config_manager: Arc<dyn ConfigManager>,
441        proto_processor: Arc<dyn ProtoProcessor>,
442        cache_manager: Arc<dyn CacheManager>,
443    ) -> Self {
444        Self {
445            config_manager,
446            proto_processor,
447            cache_manager,
448        }
449    }
450
451    /// 执行代码生成
452    pub async fn generate_code(&self, options: &GenerationOptions) -> Result<GenerationResult> {
453        // 1. 清理输出目录(如果需要)
454        if options.clean_before_generate {
455            self.clean_output_directory(&options.output_path).await?;
456        }
457
458        // 2. 发现本地Proto文件
459        let local_protos = self
460            .proto_processor
461            .discover_proto_files(&options.input_path)
462            .await?;
463
464        // 3. 加载依赖的Proto文件
465        let dependency_protos = self.load_dependency_protos().await?;
466
467        // 4. 验证Proto语法
468        let all_protos = [local_protos, dependency_protos].concat();
469        let validation = self
470            .proto_processor
471            .validate_proto_syntax(&all_protos)
472            .await?;
473
474        if !validation.is_valid {
475            return Err(anyhow::anyhow!("Proto文件语法验证失败"));
476        }
477
478        // 5. 执行代码生成
479        let mut generation_result = self
480            .proto_processor
481            .generate_code(&options.input_path, &options.output_path)
482            .await?;
483
484        // 6. 后处理:格式化和检查
485        if options.format_code {
486            self.format_generated_code(&generation_result.generated_files)
487                .await?;
488        }
489
490        if options.run_checks {
491            let check_result = self
492                .run_code_checks(&generation_result.generated_files)
493                .await?;
494            generation_result.warnings.extend(check_result.warnings);
495            generation_result.errors.extend(check_result.errors);
496        }
497
498        Ok(generation_result)
499    }
500
501    /// 清理输出目录
502    async fn clean_output_directory(&self, output_path: &std::path::Path) -> Result<()> {
503        if output_path.exists() {
504            std::fs::remove_dir_all(output_path)?;
505        }
506        std::fs::create_dir_all(output_path)?;
507        Ok(())
508    }
509
510    /// 加载依赖的Proto文件
511    async fn load_dependency_protos(&self) -> Result<Vec<ProtoFile>> {
512        // TODO: 从缓存中加载依赖的Proto文件
513        Ok(Vec::new())
514    }
515
516    /// 格式化生成的代码
517    async fn format_generated_code(&self, files: &[std::path::PathBuf]) -> Result<()> {
518        for file in files {
519            if file.extension().and_then(|s| s.to_str()) == Some("rs") {
520                // 运行 rustfmt
521                let output = std::process::Command::new("rustfmt").arg(file).output()?;
522
523                if !output.status.success() {
524                    eprintln!("rustfmt 警告: {}", String::from_utf8_lossy(&output.stderr));
525                }
526            }
527        }
528        Ok(())
529    }
530
531    /// 运行代码检查
532    async fn run_code_checks(&self, files: &[std::path::PathBuf]) -> Result<GenerationResult> {
533        // TODO: 运行 cargo check 或其他代码检查工具
534        Ok(GenerationResult {
535            generated_files: files.to_vec(),
536            warnings: vec![],
537            errors: vec![],
538        })
539    }
540}