Skip to content

perf(desktop): parallelize relay agent directory rebuild - #6258

Merged
wpfleger96 merged 1 commit into
mainfrom
wpfleger96/relay-directory-parallel-rebuild
Aug 18, 2026
Merged

perf(desktop): parallelize relay agent directory rebuild#6258
wpfleger96 merged 1 commit into
mainfrom
wpfleger96/relay-directory-parallel-rebuild

Conversation

@wpfleger96

@wpfleger96 wpfleger96 commented Aug 18, 2026

Copy link
Copy Markdown
Member

The shared-agent directory rebuild resolves runtime directories, owner profiles, and managed policies for every candidate agent via dozens of exact-author query batches. Issuing those batches serially made a ~100-agent rebuild take 6.5–8.4s, which dominated @mention autocomplete latency.

#6224 already scoped the send-path revalidation (revalidate_relay_agents) to just the mentioned pubkeys, so the send stall is fixed. But the autocomplete directory (list_relay_agents) still rebuilds the full membership set serially — this PR removes that remaining cost.

Change

Run the query batches with bounded concurrency via a shared query_filter_batches helper. Each directory rebuild constructs one tokio::sync::Semaphore (8 permits) and shares it across all of that rebuild's phases, so the runtime-directory and owner-profile phases that run concurrently under one try_join! never exceed 8 /query requests in flight together — the bound is per-rebuild. The policy phase reuses the same budget. Same events, keyed by pubkey downstream so ordering is irrelevant.

Both list_relay_agents (autocomplete) and revalidate_relay_agents (scoped send-path check from #6224) funnel through list_relay_agents_for_selection, so the helper is a no-op for the tiny 1–3-mention revalidation set and only the full autocomplete rebuild sees the win — the scoped send path is untouched.

Measurement

Live on the production relay, warm connection, full list_relay_agents:

Full-directory rebuild
Serial (before) 6.5–8.4s
Bounded-concurrency (after) 2.0–3.4s

Returned pubkey set is byte-identical pre/post. The 8-permit ceiling holds under saturation (24 batched requests → peak exactly 8, zero failures, zero requests left in flight).

@wpfleger96
wpfleger96 requested a review from a team as a code owner August 18, 2026 20:23
@wpfleger96
wpfleger96 force-pushed the wpfleger96/relay-directory-parallel-rebuild branch 2 times, most recently from 57a5a30 to 34df8c2 Compare August 18, 2026 21:01

@wesbillman wesbillman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Source review: the change preserves the existing exact-author filters and downstream conversion, but replaces 10 sequential directory/profile batch rounds plus sequential policy rounds with a shared 8-permit budget. For ~95 candidates that reduces the dominant work from roughly 20 network-latency rounds to about 5 while preserving the prior all-or-error behavior. The same semaphore is shared by the concurrently-polled directory/profile phases, and each permit lives through query_relay, so a rebuild cannot exceed eight in-flight /query calls. Scoped send-time revalidation still filters membership before constructing these queries, so its 1–3-agent path remains one batch per phase.

I found no correctness or merge-safety defect. CI at head 34df8c2af3a2b928fde13e930aa94ab2810c428c is green, including Desktop Core (2552 passed), Rust lint, macOS/Windows builds, and desktop E2E.

Review limitation: per the strict code-review channel contract I did not run a build, test, relay, or app locally. The reported production timing and byte-identical result set therefore remain author-provided performance evidence rather than an independent runtime measurement.

@wesbillman wesbillman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Carl, an automated reviewer, commenting via Wes’s GitHub account.

The concurrency change itself is sound: it preserves the exact 10-filter request partition and all-or-error behavior, shares one 8-permit budget across the concurrently-polled directory/profile phases, and leaves selected-pubkey send revalidation scoped. The reported 6.5–8.4s to 2.0–3.4s result is structurally consistent with reducing roughly 20 serialized request waves to about 5, though I did not independently repeat the production benchmark. CI is green at 34df8c2af3a2b928fde13e930aa94ab2810c428c.

One small required fix before merge: query_filter_batches adds a production .expect(...) when acquiring the semaphore. AGENTS.md explicitly prohibits new unwrap()/expect() calls in production paths. The local semaphore is never closed, so this is not a demonstrated runtime bug, but it is unnecessary and violates the repository contract. Please propagate the acquisition error instead, for example:

let _permit = semaphore
    .acquire()
    .await
    .map_err(|error| format!("directory concurrency semaphore closed: {error}"))?;

With that mechanical cleanup, I found no correctness, authorization, ordering, stale-state, or load-bound blocker and consider the change safe to merge.

The shared-agent directory rebuild fans dozens of exact-author query
batches across the relay to resolve runtime directories, owner profiles,
and managed policies for every candidate. Issuing those batches serially
made a ~100-agent rebuild take 6.5-8.4s, which dominated @mention
autocomplete latency.

Run the batches with bounded concurrency via a shared query_filter_batches
helper. A single tokio Semaphore caps /query requests at 8 across every
phase, so the runtime-directory and owner-profile phases that run
concurrently under one try_join! never exceed the ceiling together. Same
events, keyed by pubkey downstream so order is irrelevant. Live-measured on
the production relay (95 agents, identical returned pubkey set): 6.5-8.4s
-> 2.0-3.4s.

Co-authored-by: Will Pfleger <pfleger.will@gmail.com>
Signed-off-by: Will Pfleger <pfleger.will@gmail.com>
@wpfleger96
wpfleger96 force-pushed the wpfleger96/relay-directory-parallel-rebuild branch from 34df8c2 to 3dd99d1 Compare August 18, 2026 22:13

@wesbillman wesbillman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Carl, an automated reviewer, commenting via Wes’s GitHub account.

Royal Court verdict: APPROVE

Reviewed exact head 3dd99d1bfa45fde27085ddb15fb49b6872ef212b. The requested cleanup is complete: semaphore acquisition now propagates a labeled error with map_err(...)? instead of using production .expect(...). The error label remains attached to both acquisition and relay-query failures, and the concurrency, filtering, ordering, cancellation, and fail-closed behavior reviewed at the prior head is otherwise unchanged.

git diff --check passes for the corrective delta. Rust lint, DCO, release candidate, changed-path guard, dead-token guard, Desktop E2E relay, and one integration shard are already green at this head; remaining exact-head Desktop, smoke, integration, Windows, and macOS jobs were still running when this approval was submitted. Merge after required CI completes successfully.

This approval expires if HEAD moves.

@wpfleger96
wpfleger96 enabled auto-merge (squash) August 18, 2026 22:31
@wpfleger96
wpfleger96 merged commit a362fec into main Aug 18, 2026
24 checks passed
@wpfleger96
wpfleger96 deleted the wpfleger96/relay-directory-parallel-rebuild branch August 18, 2026 22:35
jedwards27 pushed a commit to jedwards27/buzz that referenced this pull request Aug 18, 2026
* origin/main: (43 commits)
  perf(desktop): parallelize relay agent directory rebuild (block#6258)
  Refine the mobile emoji picker (block#5853)
  fix(desktop): exclude archived agents from nest, order regeneration (block#5905)
  Add font size and conversation density preferences (block#5644)
  fix(desktop): emit camelCase config-write payload fields (block#6062)
  fix(desktop): downscale large avatars for agent-share PNG body (block#6260)
  fix(desktop): preserve early relay auth challenges (block#3320)
  Polish mobile message actions (block#5873)
  Refine mobile pairing confirmation (block#6018)
  chore(scripts): add buzz-adopt-prod-agents.sh (block#6250)
  feat(managed-agents): close five Claude Code agent-config gaps (block#4557)
  chore(hooks): keep mobile analysis out of pre-commit (block#6236)
  fix(shared-ui): delay hover disclosures by default (block#5821)
  fix(desktop-chrome): preserve balanced layout when sidebar collapses (block#6000)
  Polish mobile timeline navigation (block#5874)
  chore(release): release Buzz Desktop version 0.5.17 (block#6234)
  fix(prompt): simplify pickup follow-through (block#6186)
  fix(mcp): scope todo usage (block#6216)
  fix(desktop): bound remote agent mention authorization (block#6224)
  fix: bump h2 for RUSTSEC-2026-0258 (block#6222)
  ...

Signed-off-by: Princess Donut <3cb959c7eb65d61f634e61df318e450f18f82fa0e01849e7010b82666ead0587@buzz.block.builderlab.xyz>

# Conflicts:
#	desktop/src/main.tsx
#	mobile/ios/Podfile.lock
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants