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
}
/// 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!(

View File

@@ -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<dyn std::error::Error>, 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,