Skip to content

perf(sessions): coalesce eager-fetch progress and memoize list roots - #563

Open
RonenMars wants to merge 1 commit into
mainfrom
perf/coalesce-eager-progress
Open

perf(sessions): coalesce eager-fetch progress and memoize list roots#563
RonenMars wants to merge 1 commit into
mainfrom
perf/coalesce-eager-progress

Conversation

@RonenMars

@RonenMars RonenMars commented Aug 8, 2026

Copy link
Copy Markdown
Owner

Scope (partial improvement — not the full fix)

This PR paces two sources of re-render churn on the Hub during the "Showing cached data — syncing" state, but on-device measurement (see #564 / #565) showed it does not by itself stop the sustained re-render loop.
Treat it as a smaller, complementary improvement to the root-cause fixes in #566, not as "the fix" for the slow syncing state.

What it does

  1. Coalesce the eager-fetch progress setState in useEagerSessions and useEagerConversations with useThrottledCallback (250 ms, .flush() on completion so the final counter stays exact).
    This collapses the per-page progress bursts from ~15-20 root re-renders per refresh to a handful, and applies to all three views because the hooks live once at the Hub root.
  2. Wrap the four list roots — TreeSessionsList, ProjectHubList, ClassicSessionsList, MergedClassicList — in React.memo so stable-prop drain ticks skip re-running the list for tree, hub, and classic alike.

No behavior change: React.memo only skips a re-render when props are shallow-equal, and every list prop is a fresh ref from useMemo/state.

Why it isn't the whole story

On-device tracing with a per-commit probe found the Hub still re-rendering continuously after this change, driven by two things this PR does not touch:

Both are fixed in #566, which is what actually stops the loop (render rate ~6/sec → ~0.65/sec on-device). This PR remains worthwhile because it bounds the per-page progress bursts that #566 does not address.

Verification

ESLint clean; tsc no new errors (the repo-wide router.push typed-routes errors are pre-existing and unrelated).
Unit: useSession.test 5/5 and ServerRowRefreshing 10/10 pass locally; useConversations.test left to CI.

The Hub eager-fetches every sessions/conversations page for every server on each refresh, and both hooks wrote loaded/total to state on every page tick — 15-20 full re-renders of the Hub root per refresh while showing cached data.
Coalesce those writes with useThrottledCallback (250ms, trailing flush on completion so the final counter stays exact) in useEagerSessions and useEagerConversations.
Wrap the four list roots (TreeSessionsList, ProjectHubList, ClassicSessionsList, MergedClassicList) in React.memo so stable-prop drain ticks skip re-running the list for tree, hub, and classic views alike.
No behavior change: memo only skips re-renders when props are shallow-equal, and every list prop is a fresh ref from useMemo/state.
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.

1 participant