From deafa88af5a799a079bf0a92986dcdc8fb29b02e Mon Sep 17 00:00:00 2001 From: Taylor Eernisse Date: Tue, 3 Feb 2026 14:09:44 -0500 Subject: [PATCH] perf: Concurrent resource event fetching, remove unnecessary async client.rs: - fetch_all_resource_events() now uses tokio::try_join!() to fire all three API requests (state, label, milestone events) concurrently instead of awaiting each sequentially. For entities with many events, this reduces wall-clock time by up to ~3x since the three independent HTTP round-trips overlap. main.rs: - Removed async from handle_issues() and handle_mrs(). These functions perform only synchronous database queries and formatting; they never await anything. Removing the async annotation avoids the overhead of an unnecessary Future state machine and makes the sync nature of these code paths explicit. Co-Authored-By: Claude Opus 4.5 --- src/gitlab/client.rs | 26 +++++++++++--------------- src/main.rs | 8 ++++---- 2 files changed, 15 insertions(+), 19 deletions(-) diff --git a/src/gitlab/client.rs b/src/gitlab/client.rs index ade4dde..117e7af 100644 --- a/src/gitlab/client.rs +++ b/src/gitlab/client.rs @@ -662,7 +662,7 @@ impl GitLabClient { self.fetch_all_pages(&path).await } - /// Fetch all three event types for an entity in one call. + /// Fetch all three event types for an entity concurrently. pub async fn fetch_all_resource_events( &self, gitlab_project_id: i64, @@ -675,23 +675,19 @@ impl GitLabClient { )> { match entity_type { "issue" => { - let state = self - .fetch_issue_state_events(gitlab_project_id, iid) - .await?; - let label = self - .fetch_issue_label_events(gitlab_project_id, iid) - .await?; - let milestone = self - .fetch_issue_milestone_events(gitlab_project_id, iid) - .await?; + let (state, label, milestone) = tokio::try_join!( + self.fetch_issue_state_events(gitlab_project_id, iid), + self.fetch_issue_label_events(gitlab_project_id, iid), + self.fetch_issue_milestone_events(gitlab_project_id, iid), + )?; Ok((state, label, milestone)) } "merge_request" => { - let state = self.fetch_mr_state_events(gitlab_project_id, iid).await?; - let label = self.fetch_mr_label_events(gitlab_project_id, iid).await?; - let milestone = self - .fetch_mr_milestone_events(gitlab_project_id, iid) - .await?; + let (state, label, milestone) = tokio::try_join!( + self.fetch_mr_state_events(gitlab_project_id, iid), + self.fetch_mr_label_events(gitlab_project_id, iid), + self.fetch_mr_milestone_events(gitlab_project_id, iid), + )?; Ok((state, label, milestone)) } _ => Err(LoreError::Other(format!( diff --git a/src/main.rs b/src/main.rs index b8dae7a..1293b68 100644 --- a/src/main.rs +++ b/src/main.rs @@ -72,8 +72,8 @@ async fn main() { let quiet = cli.quiet; let result = match cli.command { - Commands::Issues(args) => handle_issues(cli.config.as_deref(), args, robot_mode).await, - Commands::Mrs(args) => handle_mrs(cli.config.as_deref(), args, robot_mode).await, + Commands::Issues(args) => handle_issues(cli.config.as_deref(), args, robot_mode), + Commands::Mrs(args) => handle_mrs(cli.config.as_deref(), args, robot_mode), Commands::Search(args) => handle_search(cli.config.as_deref(), args, robot_mode).await, Commands::Stats(args) => handle_stats(cli.config.as_deref(), args, robot_mode).await, Commands::Embed(args) => handle_embed(cli.config.as_deref(), args, robot_mode).await, @@ -284,7 +284,7 @@ fn handle_error(e: Box, robot_mode: bool) -> ! { // Primary command handlers // ============================================================================ -async fn handle_issues( +fn handle_issues( config_override: Option<&str>, args: IssuesArgs, robot_mode: bool, @@ -334,7 +334,7 @@ async fn handle_issues( Ok(()) } -async fn handle_mrs( +fn handle_mrs( config_override: Option<&str>, args: MrsArgs, robot_mode: bool,