feat(sessions): summary poll — stop shipping the full list on non-list routes (v0.296.0) - #542
Merged
Merged
Conversation
…t routes (v0.296.0) Sessions-pagination Phase 2 (plan: docs/sessions-pagination-plan.md). The console's 1.5s poll shipped all ~950 sessions every tick on every route. New GET /api/sessions/summary returns only the always-on rows — every LIVE session + the viewer's recent-ended tail (cap 60) + a global doneToday count — built from aliveNames() + a bounded id query + listSessions(ids), viewer-scoped, never rebuilding the whole table. The global poll now switches source by route: the Sessions & Chat list views still fetch full /api/sessions (they render it); every OTHER route polls the summary. So navigating Inbox/Tasks/Overview/Agents/Settings no longer pulls ~950 rows per tick. openNotification falls back to the Phase-1 by-id fetch for an older session not in the summary; Overview's doneToday reads the summary count (owner-only → global count is correct); mutation handlers reload via the route-appropriate endpoint. Badge (messages) and per-session bells (blocked ⊂ live) unaffected. Measured on a live instawp snapshot (950 rows): poll payload 950 → ~68 rows off the list routes; summary builds ~23-33% faster than the full list before the row-count win. Verified: in-process endpoint test (bounded/viewer-scoped/304/doneToday) + headless browser smoke (inbox polls summary, zero full-list calls; sessions route renders all 950; Overview KPI; no console errors). Typecheck + web build + test:governance (29/29) green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
vikasprogrammer
added a commit
that referenced
this pull request
Aug 3, 2026
…rtualize now, paginate later) (#544) Adds a "Console performance" section to TODO.md tracking the shipped console-perf arc (Phases 1+2, #539/#542) and the Phase 3 decision: do client row virtualization first (3a, low-risk render fix), defer server-side pagination (3b) until a tenant's session count clears ~3-5k. Updates docs/sessions-pagination-plan.md Status to match. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Sessions-pagination Phase 2. Plan:
docs/sessions-pagination-plan.md. Builds on Phase 1 (#539).Problem
The console's 1.5 s poll shipped all ~950 sessions every tick, on every route — even Inbox/Tasks/Overview/Settings, which never render the list. #530/#532 made unchanged ticks cheap on the wire, but the server still rebuilt 950 rows each tick and any change re-shipped them.
Change
New
GET /api/sessions/summaryreturns only the always-on rows — every LIVE session + the viewer's most-recent ended tail (capped 60) + a globaldoneTodaycount — built fromaliveNames()+ a bounded id query +listSessions(ids), viewer-scoped, never rebuilding the whole table.The global poll now switches source by route: the Sessions & Chat list views still fetch full
/api/sessions(they render it); every other route polls the summary. So most navigation stops pulling ~950 rows per tick.Kept correct via the reader map (see plan):
messages(untouched); per-session bells fromblocked(⊂ live, always in the summary).openNotificationfalls back to the Phase-1 by-id fetch for an older session not in the summary.doneTodayreads the summary count (Overview is owner-only → a global count is correct).reloadSessions), never re-inflating a summary route with the full list.SessionsPage/ChatPage/OverviewPageinternals unchanged — they still receive asessionsarray, sourced full on their own routes.Measured (live instawp snapshot, 950 rows)
listSessions, before the row-count/wire win.Verification
doneTodaymatches a direct count, 304 on unchanged tick, viewer-scoped (a member sees 0 unowned rows)./api/sessions/summarywith zero full-list calls; the sessions route switches to the full list and renders "950 sessions"; Overview polls summary + renders "Done today"; no console/page errors.npm run test:governance(29/29) green.Next
Phase 3 — server-side pagination + filter/sort/search on
/api/sessionsso the list view itself scales (it still fetches the full list when open). See the plan doc.🤖 Generated with Claude Code