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            "Installed {} dependencies, updated {} cache entries",
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: &Config) -> Result<Vec<DependencySpec>> {
272        let mut specs = Vec::new();
273
274        for dependency in &config.dependencies {
275            let uri = format!(
276                "actr://{}:{}+{}@v1/",
277                dependency.realm.realm_id,
278                dependency.actr_type.manufacturer,
279                dependency.actr_type.name
280            );
281            specs.push(DependencySpec {
282                name: dependency.alias.clone(),
283                uri,
284                version: None,
285                fingerprint: dependency.fingerprint.clone(),
286            });
287        }
288
289        Ok(specs)
290    }
291}
292
293// ============================================================================
294// 2. 安装管道 (InstallPipeline)
295// ============================================================================
296
297/// 安装管道 - 基于ValidationPipeline构建
298pub struct InstallPipeline {
299    validation_pipeline: ValidationPipeline,
300    config_manager: Arc<dyn ConfigManager>,
301    cache_manager: Arc<dyn CacheManager>,
302    #[allow(dead_code)]
303    proto_processor: Arc<dyn ProtoProcessor>,
304}
305
306impl InstallPipeline {
307    pub fn new(
308        validation_pipeline: ValidationPipeline,
309        config_manager: Arc<dyn ConfigManager>,
310        cache_manager: Arc<dyn CacheManager>,
311        proto_processor: Arc<dyn ProtoProcessor>,
312    ) -> Self {
313        Self {
314            validation_pipeline,
315            config_manager,
316            cache_manager,
317            proto_processor,
318        }
319    }
320
321    /// Check-First 安装流程
322    pub async fn install_dependencies(&self, specs: &[DependencySpec]) -> Result<InstallResult> {
323        // 🔍 阶段1: 完整验证 (复用ValidationPipeline)
324        let validation_report = self
325            .validation_pipeline
326            .validate_dependencies(specs)
327            .await?;
328
329        // 检查验证结果
330        let failed_validations: Vec<_> = validation_report
331            .iter()
332            .filter(|v| !v.is_available)
333            .collect();
334
335        if !failed_validations.is_empty() {
336            return Err(anyhow::anyhow!(
337                "依赖验证失败: {}",
338                failed_validations
339                    .iter()
340                    .map(|v| format!(
341                        "{}: {}",
342                        v.dependency,
343                        v.error.as_deref().unwrap_or("unknown error")
344                    ))
345                    .collect::<Vec<_>>()
346                    .join(", ")
347            ));
348        }
349
350        // 📝 阶段2: 原子性安装
351        let backup = self.config_manager.backup_config().await?;
352
353        match self.execute_atomic_install(specs).await {
354            Ok(result) => {
355                // 安装成功,清理备份
356                self.config_manager.remove_backup(backup).await?;
357                Ok(result)
358            }
359            Err(e) => {
360                // 安装失败,恢复备份
361                self.config_manager.restore_backup(backup).await?;
362                Err(e)
363            }
364        }
365    }
366
367    /// 原子性安装执行
368    async fn execute_atomic_install(&self, specs: &[DependencySpec]) -> Result<InstallResult> {
369        let mut result = InstallResult::success();
370
371        for spec in specs {
372            // 1. 更新配置文件
373            self.config_manager.update_dependency(spec).await?;
374            result.updated_config = true;
375
376            // 2. 获取服务详情并缓存Proto文件
377            let service_details = self
378                .validation_pipeline
379                .service_discovery
380                .get_service_details(&spec.uri)
381                .await?;
382
383            self.cache_manager
384                .cache_proto(&spec.uri, &service_details.proto_files)
385                .await?;
386            result.cache_updates += 1;
387
388            // 3. 记录已安装的依赖
389            let resolved_dep = ResolvedDependency {
390                spec: spec.clone(),
391                uri: spec.uri.clone(),
392                resolved_version: service_details.info.version,
393                fingerprint: service_details.info.fingerprint,
394                proto_files: service_details.proto_files,
395            };
396            result.installed_dependencies.push(resolved_dep);
397        }
398
399        // 4. 更新锁文件
400        self.update_lock_file(&result.installed_dependencies)
401            .await?;
402        result.updated_lock_file = true;
403
404        Ok(result)
405    }
406
407    /// Update lock file
408    async fn update_lock_file(&self, dependencies: &[ResolvedDependency]) -> Result<()> {
409        // TODO: Implement lock file update logic
410        // Should read existing lock file, merge new dependency info, then write back
411        println!("Updating lock file: {} dependencies", dependencies.len());
412        Ok(())
413    }
414}
415
416// ============================================================================
417// 3. 生成管道 (GenerationPipeline)
418// ============================================================================
419
420/// 代码生成管道
421pub struct GenerationPipeline {
422    #[allow(dead_code)]
423    config_manager: Arc<dyn ConfigManager>,
424    proto_processor: Arc<dyn ProtoProcessor>,
425    #[allow(dead_code)]
426    cache_manager: Arc<dyn CacheManager>,
427}
428
429impl GenerationPipeline {
430    pub fn new(
431        config_manager: Arc<dyn ConfigManager>,
432        proto_processor: Arc<dyn ProtoProcessor>,
433        cache_manager: Arc<dyn CacheManager>,
434    ) -> Self {
435        Self {
436            config_manager,
437            proto_processor,
438            cache_manager,
439        }
440    }
441
442    /// 执行代码生成
443    pub async fn generate_code(&self, options: &GenerationOptions) -> Result<GenerationResult> {
444        // 1. 清理输出目录(如果需要)
445        if options.clean_before_generate {
446            self.clean_output_directory(&options.output_path).await?;
447        }
448
449        // 2. 发现本地Proto文件
450        let local_protos = self
451            .proto_processor
452            .discover_proto_files(&options.input_path)
453            .await?;
454
455        // 3. 加载依赖的Proto文件
456        let dependency_protos = self.load_dependency_protos().await?;
457
458        // 4. 验证Proto语法
459        let all_protos = [local_protos, dependency_protos].concat();
460        let validation = self
461            .proto_processor
462            .validate_proto_syntax(&all_protos)
463            .await?;
464
465        if !validation.is_valid {
466            return Err(anyhow::anyhow!("Proto file syntax validation failed"));
467        }
468
469        // 5. 执行代码生成
470        let mut generation_result = self
471            .proto_processor
472            .generate_code(&options.input_path, &options.output_path)
473            .await?;
474
475        // 6. 后处理:格式化和检查
476        if options.format_code {
477            self.format_generated_code(&generation_result.generated_files)
478                .await?;
479        }
480
481        if options.run_checks {
482            let check_result = self
483                .run_code_checks(&generation_result.generated_files)
484                .await?;
485            generation_result.warnings.extend(check_result.warnings);
486            generation_result.errors.extend(check_result.errors);
487        }
488
489        Ok(generation_result)
490    }
491
492    /// 清理输出目录
493    async fn clean_output_directory(&self, output_path: &std::path::Path) -> Result<()> {
494        if output_path.exists() {
495            std::fs::remove_dir_all(output_path)?;
496        }
497        std::fs::create_dir_all(output_path)?;
498        Ok(())
499    }
500
501    /// 加载依赖的Proto文件
502    async fn load_dependency_protos(&self) -> Result<Vec<ProtoFile>> {
503        // TODO: 从缓存中加载依赖的Proto文件
504        Ok(Vec::new())
505    }
506
507    /// 格式化生成的代码
508    async fn format_generated_code(&self, files: &[std::path::PathBuf]) -> Result<()> {
509        for file in files {
510            if file.extension().and_then(|s| s.to_str()) == Some("rs") {
511                // 运行 rustfmt
512                let output = std::process::Command::new("rustfmt").arg(file).output()?;
513
514                if !output.status.success() {
515                    eprintln!(
516                        "rustfmt warning: {}",
517                        String::from_utf8_lossy(&output.stderr)
518                    );
519                }
520            }
521        }
522        Ok(())
523    }
524
525    /// 运行代码检查
526    async fn run_code_checks(&self, files: &[std::path::PathBuf]) -> Result<GenerationResult> {
527        // TODO: 运行 cargo check 或其他代码检查工具
528        Ok(GenerationResult {
529            generated_files: files.to_vec(),
530            warnings: vec![],
531            errors: vec![],
532        })
533    }
534}