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 <noreply@anthropic.com>
This commit is contained in:
Taylor Eernisse
2026-02-03 14:09:44 -05:00
parent 880ad1d3fa
commit deafa88af5
2 changed files with 15 additions and 19 deletions

View File

@@ -662,7 +662,7 @@ impl GitLabClient {
self.fetch_all_pages(&path).await 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( pub async fn fetch_all_resource_events(
&self, &self,
gitlab_project_id: i64, gitlab_project_id: i64,
@@ -675,23 +675,19 @@ impl GitLabClient {
)> { )> {
match entity_type { match entity_type {
"issue" => { "issue" => {
let state = self let (state, label, milestone) = tokio::try_join!(
.fetch_issue_state_events(gitlab_project_id, iid) self.fetch_issue_state_events(gitlab_project_id, iid),
.await?; self.fetch_issue_label_events(gitlab_project_id, iid),
let label = self self.fetch_issue_milestone_events(gitlab_project_id, iid),
.fetch_issue_label_events(gitlab_project_id, iid) )?;
.await?;
let milestone = self
.fetch_issue_milestone_events(gitlab_project_id, iid)
.await?;
Ok((state, label, milestone)) Ok((state, label, milestone))
} }
"merge_request" => { "merge_request" => {
let state = self.fetch_mr_state_events(gitlab_project_id, iid).await?; let (state, label, milestone) = tokio::try_join!(
let label = self.fetch_mr_label_events(gitlab_project_id, iid).await?; self.fetch_mr_state_events(gitlab_project_id, iid),
let milestone = self self.fetch_mr_label_events(gitlab_project_id, iid),
.fetch_mr_milestone_events(gitlab_project_id, iid) self.fetch_mr_milestone_events(gitlab_project_id, iid),
.await?; )?;
Ok((state, label, milestone)) Ok((state, label, milestone))
} }
_ => Err(LoreError::Other(format!( _ => Err(LoreError::Other(format!(

View File

@@ -72,8 +72,8 @@ async fn main() {
let quiet = cli.quiet; let quiet = cli.quiet;
let result = match cli.command { let result = match cli.command {
Commands::Issues(args) => handle_issues(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).await, 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::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::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, Commands::Embed(args) => handle_embed(cli.config.as_deref(), args, robot_mode).await,
@@ -284,7 +284,7 @@ fn handle_error(e: Box<dyn std::error::Error>, robot_mode: bool) -> ! {
// Primary command handlers // Primary command handlers
// ============================================================================ // ============================================================================
async fn handle_issues( fn handle_issues(
config_override: Option<&str>, config_override: Option<&str>,
args: IssuesArgs, args: IssuesArgs,
robot_mode: bool, robot_mode: bool,
@@ -334,7 +334,7 @@ async fn handle_issues(
Ok(()) Ok(())
} }
async fn handle_mrs( fn handle_mrs(
config_override: Option<&str>, config_override: Option<&str>,
args: MrsArgs, args: MrsArgs,
robot_mode: bool, robot_mode: bool,