Skip to content

fix: groups pages spinning when signed out, slow endorsement graph (TECH-806, TECH-808) - #259

Merged
holkexyz merged 2 commits into
mainfrom
holke/tech-806-808-groups-spinner-graph-perf
Oct 29, 2026
Merged

holkexyz merged 2 commits into
mainfrom
holke/tech-806-808-groups-spinner-graph-perf

Conversation

@svc-agent

@svc-agent svc-agent commented Oct 28, 2026 •

Copy link
Copy Markdown
Collaborator

Hotfix to main for two fixes already on staging (0f7a240, 65b77bf), cherry-picked without the TECH-789 commits.

TECH-806: /groups/create and /groups/import spin forever when signed out

  • OrgProvider.fetchOrgs returned early when signed out without clearing isLoading, so it stayed true.
  • useOrgCreationLimit only cleared isChecking when its did|orgsLoading key changed. If the org list had already settled at mount, nothing changed and the check stayed stuck.
  • Now both settle, and the pages show their "Sign in to ..." prompt.

TECH-808: /endorsement-graph takes ~19s to appear

  • The graph is drawn as soon as its structure is known. Handles, names and avatars are filled into the same node objects afterwards, so the force layout doesn't restart.
  • The resolve-dids batcher sends up to 3 chunks of 50 at a time instead of one after another. The server charges its rate limit per identity, so this changes speed, not request volume. After a 429, queued chunks fall back to DIDs instead of being sent into the cooldown.

Testing

  • New tests for both fixes; each fails on the old code.
  • Locally on this branch: tsc, typecheck:test, lint, lint:css, 1346 unit tests, build.
  • On staging (signed out): both groups pages show the sign-in prompt; the graph draws in ~3.3s (from ~19s on production), with three resolve-dids requests in parallel and the layout keeping its shape when labels arrive. Production has more accounts, so expect it to be slower than staging.

Not covered: whether /groups/create also hung when signed in (needs a signed-in session). TECH-807 (OAuth requestLock) is a separate fix.

🤖 Generated with Claude Code

RetriggerView in GreptileConfidence Score: 4/5

The PR appears safe to merge, with a non-blocking graph update that resets the user's zoom when names arrive.

Fix All in Claude CodeFindings

  1. P2 Names arriving reset the zoom ▶
Fix with agent prompt
### Issue 1
src/hooks/use-endorsement-graph.ts:388-389
Replacing the `nodes` array makes `EndorsementGraph` rebuild `data`. Its layout effect calls `d3ReheatSimulation()`, and `onEngineStop` then calls `zoomToFit()`. Users who zoom into the early graph while names load get zoomed back out when loading finishes. Keeping the same node objects preserves their positions, but does not prevent this restart.

Refresh labels separately from the graph structure so updates to names and avatars do not restart the layout or move the camera.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Summary

Fixes signed-out group pages and shows the endorsement graph before names and avatars finish loading.

  • Signed-out group pages now reach their sign-in prompts.
  • The endorsement graph appears before its profile details finish loading.
  • DID profile lookups send up to three chunks at once.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart TD
  A[Load graph structure] --> B[Show interactive graph]
  B --> C[Resolve names and avatars]
  C --> D[Update shared node objects]
  D --> E[Replace node array]
  E --> F[Restart layout]
  F --> G[Fit whole graph into view]
Loading

Reviews (1) · Last reviewed commit: "perf(endorsement-graph): draw the graph ..." · Reviewed by Greptile

holkexyz and others added 2 commits October 28, 2026 20:46
…ned out

Signed out, OrgProvider returned before fetching without clearing
isLoading, so every page waiting on the org list sat on its spinner
forever instead of showing the sign-in prompt. useOrgCreationLimit had
the same hang on its own since c749825: its render-time reset only
fires when the did|orgsLoading key changes, so with the org list
already settled at mount, isChecking stayed true. It now reports
isChecking only while there is a signed-in DID to check.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
On production the graph took about 19s to appear: about 6s of indexer
pages, then about 12s resolving ~240 DIDs in five 50-DID requests sent
one after another, and only then the first draw.

- useEndorsementGraph shows the graph as soon as its structure and the
  actor-profile index data are in, then fills handles and avatars into
  the same node objects (react-force-graph keeps layout positions on
  them, so the layout doesn't restart).
- The resolve-dids batcher sends up to three chunks of a flush at once.
  The server charges its rate limit per identity, so the volume is
  unchanged. After a 429, remaining chunks degrade to null instead of
  being sent into the cooldown.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@vercel

vercel Bot commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
certified-app Ready Ready Preview Oct 28, 2026 7:48pm UTC

Request Review

@coderabbitai

coderabbitai Bot commented Oct 28, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Caution

Review failed

The pull request is closed.

Finishing Touches
📝 Generate docstrings
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@holkexyz
holkexyz marked this pull request as ready for review October 29, 2026 08:26
@holkexyz
holkexyz merged commit d9679d9 into main Oct 29, 2026
7 checks passed
svc-agent pushed a commit that referenced this pull request Oct 29, 2026
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Comment on lines +388 to +389
for (const node of nodes) Object.assign(node, identity(node.id))
return { ...graph, nodes: [...nodes] }

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Names arriving reset the zoom

Replacing the nodes array makes EndorsementGraph rebuild data. Its layout effect calls d3ReheatSimulation(), and onEngineStop then calls zoomToFit(). Users who zoom into the early graph while names load get zoomed back out when loading finishes. Keeping the same node objects preserves their positions, but does not prevent this restart.

Refresh labels separately from the graph structure so updates to names and avatars do not restart the layout or move the camera.

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/hooks/use-endorsement-graph.ts
Line: 388-389

Comment:
**Names arriving reset the zoom**

Replacing the `nodes` array makes `EndorsementGraph` rebuild `data`. Its layout effect calls `d3ReheatSimulation()`, and `onEngineStop` then calls `zoomToFit()`. Users who zoom into the early graph while names load get zoomed back out when loading finishes. Keeping the same node objects preserves their positions, but does not prevent this restart.

Refresh labels separately from the graph structure so updates to names and avatars do not restart the layout or move the camera.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Fix in Claude Code Fix in Codex

This branch was successfully deployed

1 active deployment
Preview — 12e65eee Deployed Oct 28, 2026 by vercel[bot]
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