From de25303e4259d6c03a35f85513038ef657ff1bca Mon Sep 17 00:00:00 2001 From: Tomas Carnecky Date: Wed, 17 Jun 2026 17:56:35 +0200 Subject: [PATCH] Move async I/O in analyze_project_dependencies into tokio task --- .../actions/analyze_project_dependencies.rs | 39 +++++++++++-- src/core/application.rs | 22 +++----- src/core/engine/ecosystems/npm/mod.rs | 4 +- .../sections/history.rs | 4 +- src/core/platform.rs | 56 +++++++++++++++---- 5 files changed, 94 insertions(+), 31 deletions(-) diff --git a/src/core/actions/analyze_project_dependencies.rs b/src/core/actions/analyze_project_dependencies.rs index c52ea96..2be54f1 100644 --- a/src/core/actions/analyze_project_dependencies.rs +++ b/src/core/actions/analyze_project_dependencies.rs @@ -3,10 +3,16 @@ use futures::future; use tracing::instrument::WithSubscriber; use tracing::Instrument; -use crate::core::{ - application::Application, - database::pk, - engine::{DependencyUpdateOption, DiscoveredDependency}, +use crate::{ + core::{ + application::Application, + database::pk, + engine::{ + repository::{ProjectRepositorySnapshot, ProjectRepositoryView}, + DependencyUpdateOption, DiscoveredDependency, + }, + }, + tui::views, }; #[derive(Clone)] @@ -28,7 +34,8 @@ pub struct AnalyzedProjectDependencies { } pub async fn run(app: &Application, project_id: String, trigger_bumps: bool) -> Result<()> { - let snapshot = app.project_repository_snapshot(&project_id).await?; + let repository = app.project_platform_repository(&project_id).await?; + let scanners = app.scanners(); let registry_router = app.registry_router(); let handle = app.handle(); @@ -37,6 +44,20 @@ pub async fn run(app: &Application, project_id: String, trigger_bumps: bool) -> tokio::spawn( async move { + let snapshot = match repository.view().await { + Ok(view) => match snapshot_at_default_branch(view.as_ref()).await { + Ok(snapshot) => snapshot, + Err(e) => { + tracing::error!("Failed to get project repository snapshot: {}", e); + return; + } + }, + Err(e) => { + tracing::error!("Failed to get project repository view: {}", e); + return; + } + }; + // --- PHASE 1: SCAN --- // Run all scanners concurrently over the snapshot let scan_futures = scanners.iter().map(|scanner| { @@ -100,3 +121,11 @@ pub async fn run(app: &Application, project_id: String, trigger_bumps: bool) -> Ok(()) } + +async fn snapshot_at_default_branch( + view: &dyn ProjectRepositoryView, +) -> Result> { + let default_branch = view.get_default_branch().await?; + let revision = view.get_revision(default_branch.as_str()).await?; + Ok(view.snapshot(revision.as_str())) +} diff --git a/src/core/application.rs b/src/core/application.rs index d08e4b2..0fcd3f4 100644 --- a/src/core/application.rs +++ b/src/core/application.rs @@ -139,24 +139,22 @@ impl Application { RegistryRouter::new(registries) } - pub async fn project_repository_view( + pub async fn project_platform_repository( &self, project_id: &str, - ) -> Result> { + ) -> Result> { let project = self.store.project(project_id).await?; let platform = self.platforms.resolve(&project.platform)?; - platform.view(&project.repository).await + Ok(platform.repository(&project.repository)) } - pub async fn project_repository_snapshot( + pub async fn project_repository_view( &self, project_id: &str, - ) -> Result> { - let view = self.project_repository_view(&project_id).await?; - let default_branch = view.get_default_branch().await?; - let revision = view.get_revision(default_branch.as_str()).await?; - Ok(view.snapshot(revision.as_str())) + ) -> Result> { + let repository = self.project_platform_repository(project_id).await?; + repository.view().await } async fn run(mut self) -> Result<()> { @@ -185,10 +183,8 @@ impl Application { &self, project_id: &str, ) -> Result> { - let project = self.store.project(project_id).await?; - let platform = self.platforms.resolve(&project.platform)?; - - platform.mutator(&project.repository).await + let repository = self.project_platform_repository(project_id).await?; + repository.mutator().await } pub fn advisory_resolver(&self) -> Box { diff --git a/src/core/engine/ecosystems/npm/mod.rs b/src/core/engine/ecosystems/npm/mod.rs index b5b1d26..e6a051a 100644 --- a/src/core/engine/ecosystems/npm/mod.rs +++ b/src/core/engine/ecosystems/npm/mod.rs @@ -793,7 +793,9 @@ impl crate::core::engine::ecosystems::Patcher for NpmPatcher { } } - tracing::info!("Running pnpm install --lockfile-only to remove override markers from lockfile..."); + tracing::info!( + "Running pnpm install --lockfile-only to remove override markers from lockfile..." + ); let mut final_install_cmd = Command::new("pnpm"); final_install_cmd .arg("install") diff --git a/src/core/engine/pull_request_generator/sections/history.rs b/src/core/engine/pull_request_generator/sections/history.rs index 8d7a246..9e772fc 100644 --- a/src/core/engine/pull_request_generator/sections/history.rs +++ b/src/core/engine/pull_request_generator/sections/history.rs @@ -257,7 +257,9 @@ impl PullRequestSectionGenerator for HistorySection { if let Some(ref url) = github_url { body.push_str(&format!("> *Changelog truncated due to GitHub PR size limits. [View release notes on GitHub]({})*\n\n", url)); } else { - body.push_str("> *Changelog truncated due to GitHub PR size limits.*\n\n"); + body.push_str( + "> *Changelog truncated due to GitHub PR size limits.*\n\n", + ); } return Ok(Some(body)); } diff --git a/src/core/platform.rs b/src/core/platform.rs index 8701f7f..2349bc4 100644 --- a/src/core/platform.rs +++ b/src/core/platform.rs @@ -8,10 +8,14 @@ use crate::core::clients::tangled::Tangled; use crate::core::engine::repository::{ProjectRepositoryMutator, ProjectRepositoryView}; /// A seam for interacting with different project hosting platforms. -#[async_trait] pub trait ProjectPlatform: Send + Sync { - async fn view(&self, repository: &str) -> Result>; - async fn mutator(&self, repository: &str) -> Result>; + fn repository(&self, repository: &str) -> Box; +} + +#[async_trait] +pub trait ProjectPlatformRepository: Send + Sync { + async fn view(&self) -> Result>; + async fn mutator(&self) -> Result>; } /// Helper to split a repository string into owner and repo. @@ -37,15 +41,30 @@ impl GitHubPlatformAdapter { #[async_trait] impl ProjectPlatform for GitHubPlatformAdapter { - async fn view(&self, repository: &str) -> Result> { - let (owner, repo) = parse_repository(repository)?; + fn repository(&self, repository: &str) -> Box { + Box::new(GitHubPlatformRepository { + client: self.client.clone(), + repository: repository.to_string(), + }) + } +} + +struct GitHubPlatformRepository { + client: GitHub, + repository: String, +} + +#[async_trait] +impl ProjectPlatformRepository for GitHubPlatformRepository { + async fn view(&self) -> Result> { + let (owner, repo) = parse_repository(&self.repository)?; Ok(Box::new( self.client.project_repository_view(owner, repo).await?, )) } - async fn mutator(&self, repository: &str) -> Result> { - let (owner, repo) = parse_repository(repository)?; + async fn mutator(&self) -> Result> { + let (owner, repo) = parse_repository(&self.repository)?; Ok(Box::new( self.client.project_repository_mutator(owner, repo).await?, )) @@ -64,15 +83,30 @@ impl TangledPlatformAdapter { #[async_trait] impl ProjectPlatform for TangledPlatformAdapter { - async fn view(&self, repository: &str) -> Result> { - let (owner, repo) = parse_repository(repository)?; + fn repository(&self, repository: &str) -> Box { + Box::new(TangledPlatformRepository { + client: self.client.clone(), + repository: repository.to_string(), + }) + } +} + +struct TangledPlatformRepository { + client: Tangled, + repository: String, +} + +#[async_trait] +impl ProjectPlatformRepository for TangledPlatformRepository { + async fn view(&self) -> Result> { + let (owner, repo) = parse_repository(&self.repository)?; Ok(Box::new( self.client.project_repository_view(owner, repo).await?, )) } - async fn mutator(&self, repository: &str) -> Result> { - let (owner, repo) = parse_repository(repository)?; + async fn mutator(&self) -> Result> { + let (owner, repo) = parse_repository(&self.repository)?; Ok(Box::new( self.client.project_repository_mutator(owner, repo).await?, )) -- 2.51.2