From ba2eece9aac4d42eebea0dad9af0af11fd3fa0ec Mon Sep 17 00:00:00 2001 From: archipelago Date: Fri, 1 May 2026 15:22:07 -0400 Subject: [PATCH] refactor(container): drop unused dependency_resolver module DependencyResolver had zero call sites in prod or tests outside the module itself. The actual install-time dependency check lives in install.rs::detect_running_deps + check_install_deps; this DAG-walk solver was never wired up. -268 LoC. Co-Authored-By: Claude Opus 4.7 (1M context) --- core/container/src/dependency_resolver.rs | 268 ---------------------- core/container/src/lib.rs | 2 - 2 files changed, 270 deletions(-) delete mode 100644 core/container/src/dependency_resolver.rs diff --git a/core/container/src/dependency_resolver.rs b/core/container/src/dependency_resolver.rs deleted file mode 100644 index 438b1cb8..00000000 --- a/core/container/src/dependency_resolver.rs +++ /dev/null @@ -1,268 +0,0 @@ -use crate::manifest::{AppManifest, Dependency}; -use indexmap::IndexMap; -use std::collections::{HashMap, HashSet}; -use thiserror::Error; - -#[derive(Debug, Error)] -pub enum DependencyError { - #[error("Circular dependency detected: {0}")] - CircularDependency(String), - #[error("Missing dependency: {0}")] - MissingDependency(String), - #[error("Version conflict: {0}")] - VersionConflict(String), -} - -pub struct DependencyResolver { - manifests: IndexMap, -} - -impl DependencyResolver { - pub fn new() -> Self { - Self { - manifests: IndexMap::new(), - } - } - - pub fn add_manifest(&mut self, manifest: AppManifest) { - self.manifests.insert(manifest.app.id.clone(), manifest); - } - - pub fn resolve_dependencies(&self, app_id: &str) -> Result, DependencyError> { - let mut visited = HashSet::new(); - let mut visiting = HashSet::new(); - let mut result = Vec::new(); - - self.resolve_recursive(app_id, &mut visited, &mut visiting, &mut result)?; - - // Result is already in installation order (dependencies first) - Ok(result) - } - - fn resolve_recursive( - &self, - app_id: &str, - visited: &mut HashSet, - visiting: &mut HashSet, - result: &mut Vec, - ) -> Result<(), DependencyError> { - if visited.contains(app_id) { - return Ok(()); - } - - if visiting.contains(app_id) { - return Err(DependencyError::CircularDependency(format!( - "Circular dependency detected involving: {}", - app_id - ))); - } - - visiting.insert(app_id.to_string()); - - let manifest = self.manifests.get(app_id).ok_or_else(|| { - DependencyError::MissingDependency(format!("App not found: {}", app_id)) - })?; - - // Resolve all dependencies first - for dep in &manifest.app.dependencies { - match dep { - Dependency::App { - app_id: dep_id, - version: _, - } => { - self.resolve_recursive(dep_id, visited, visiting, result)?; - } - Dependency::Storage { storage: _ } => { - // Storage dependencies are checked but don't require other apps - } - Dependency::Simple(dep_id) => { - self.resolve_recursive(dep_id, visited, visiting, result)?; - } - } - } - - visiting.remove(app_id); - visited.insert(app_id.to_string()); - - if !result.contains(&app_id.to_string()) { - result.push(app_id.to_string()); - } - - Ok(()) - } - - pub fn check_conflicts(&self, app_id: &str) -> Result<(), DependencyError> { - let manifest = self.manifests.get(app_id).ok_or_else(|| { - DependencyError::MissingDependency(format!("App not found: {}", app_id)) - })?; - - // Check for port conflicts - let mut port_usage: HashMap = HashMap::new(); - - for (id, m) in &self.manifests { - if id == app_id { - continue; - } - - for port in &m.app.ports { - if let Some(existing) = port_usage.get(&port.host) { - return Err(DependencyError::VersionConflict(format!( - "Port {} already used by {}", - port.host, existing - ))); - } - port_usage.insert(port.host, id.clone()); - } - } - - // Check for new app's ports - for port in &manifest.app.ports { - if let Some(existing) = port_usage.get(&port.host) { - return Err(DependencyError::VersionConflict(format!( - "Port {} already used by {}", - port.host, existing - ))); - } - } - - Ok(()) - } - - pub fn calculate_resources(&self, app_ids: &[String]) -> ResourceRequirements { - let mut total = ResourceRequirements { - cpu: 0, - memory_mb: 0, - disk_gb: 0, - }; - - for app_id in app_ids { - if let Some(manifest) = self.manifests.get(app_id) { - if let Some(cpu) = manifest.app.resources.cpu_limit { - total.cpu += cpu; - } - - if let Some(memory) = &manifest.app.resources.memory_limit { - // Parse memory string (e.g., "1Gi", "512Mi") - if let Ok(mb) = parse_memory(memory) { - total.memory_mb += mb; - } - } - - if let Some(disk) = &manifest.app.resources.disk_limit { - // Parse disk string (e.g., "10Gi", "500Mi") - if let Ok(gb) = parse_disk(disk) { - total.disk_gb += gb; - } - } - } - } - - total - } -} - -fn parse_memory(s: &str) -> Result { - let s = s.trim().to_lowercase(); - if s.ends_with("gi") { - let num: f64 = s.trim_end_matches("gi").parse().map_err(|_| ())?; - Ok((num * 1024.0) as u32) - } else if s.ends_with("mi") { - let num: f64 = s.trim_end_matches("mi").parse().map_err(|_| ())?; - Ok(num as u32) - } else { - Err(()) - } -} - -fn parse_disk(s: &str) -> Result { - let s = s.trim().to_lowercase(); - if s.ends_with("gi") { - let num: f64 = s.trim_end_matches("gi").parse().map_err(|_| ())?; - Ok(num as u32) - } else if s.ends_with("ti") { - let num: f64 = s.trim_end_matches("ti").parse().map_err(|_| ())?; - Ok((num * 1024.0) as u32) - } else { - Err(()) - } -} - -#[derive(Debug, Clone)] -pub struct ResourceRequirements { - pub cpu: u32, - pub memory_mb: u32, - pub disk_gb: u32, -} - -impl Default for DependencyResolver { - fn default() -> Self { - Self::new() - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::manifest::{AppDefinition, AppManifest, ContainerConfig}; - - fn create_test_manifest(id: &str, deps: Vec) -> AppManifest { - AppManifest { - app: AppDefinition { - id: id.to_string(), - name: format!("Test {}", id), - version: "1.0.0".to_string(), - description: None, - container: ContainerConfig { - image: Some(format!("test/{}:latest", id)), - image_signature: None, - pull_policy: "if-not-present".to_string(), - build: None, - network: None, - custom_args: vec![], - entrypoint: None, - derived_env: vec![], - secret_env: vec![], - data_uid: None, - }, - dependencies: deps, - resources: Default::default(), - security: Default::default(), - ports: vec![], - volumes: vec![], - environment: vec![], - health_check: None, - devices: vec![], - extensions: Default::default(), - }, - } - } - - #[test] - fn test_simple_dependency() { - let mut resolver = DependencyResolver::new(); - resolver.add_manifest(create_test_manifest("app1", vec![])); - resolver.add_manifest(create_test_manifest( - "app2", - vec![Dependency::Simple("app1".to_string())], - )); - - let deps = resolver.resolve_dependencies("app2").unwrap(); - assert_eq!(deps, vec!["app1", "app2"]); - } - - #[test] - fn test_circular_dependency() { - let mut resolver = DependencyResolver::new(); - resolver.add_manifest(create_test_manifest( - "app1", - vec![Dependency::Simple("app2".to_string())], - )); - resolver.add_manifest(create_test_manifest( - "app2", - vec![Dependency::Simple("app1".to_string())], - )); - - let result = resolver.resolve_dependencies("app1"); - assert!(result.is_err()); - } -} diff --git a/core/container/src/lib.rs b/core/container/src/lib.rs index 5ac3965b..5f828aa5 100644 --- a/core/container/src/lib.rs +++ b/core/container/src/lib.rs @@ -1,5 +1,4 @@ pub mod bitcoin_simulator; -pub mod dependency_resolver; pub mod health_monitor; pub mod manifest; pub mod podman_client; @@ -7,7 +6,6 @@ pub mod port_manager; pub mod runtime; pub use bitcoin_simulator::{BitcoinSimulationMode, BitcoinSimulator}; -pub use dependency_resolver::DependencyResolver; pub use health_monitor::HealthMonitor; pub use manifest::{ AppManifest, BuildConfig, ContainerConfig, Dependency, DerivedEnv, HealthCheck, HostFacts,