Skip to content

Batch and preload log row data with throttled requests#21

Closed
SyntaxColoring wants to merge 1 commit into
mainfrom
cursor/batched-row-loading-8232
Closed

Batch and preload log row data with throttled requests#21
SyntaxColoring wants to merge 1 commit into
mainfrom
cursor/batched-row-loading-8232

Conversation

@SyntaxColoring

Copy link
Copy Markdown
Owner

Currently, on the log view page, each visible row makes its own request to the backend to load its entry. This change replaces that with a single batched loader hook attached to the LogView body, driven by Virtuoso's itemsRendered callback.

Behavior

  • Trigger distance: a load fires when the visible range comes within 50 rows of either edge of the currently-cached range (or when there's no cache yet).
  • Preload distance: each load eagerly fetches 200 rows beyond the visible range on both sides in a single logSearcher.getEntries() call.
  • Discarding: after each load, anything outside the (visible ± 200) window is dropped from the in-memory cache.
  • Throttling: at most one request is in flight at a time. If the visible range shifts while a load is running, we let it finish and then immediately issue a follow-up. This guarantees the cache eventually catches up to the current scroll position even after a fast scroll. Later queries effectively clobber earlier ones — when an in-flight load returns and its data is no longer near the visible range, we keep none of it and dispatch a fresh request.
  • Race-safety on filter changes: the loader is held in component state and is swapped (with the old one disposed) synchronously when logSearcher or entryNumbers change. The cache is cleared in the same render so data from a previous filter set is never shown, even briefly. In-flight loads from the previous filter set become no-ops.

Other changes

  • Virtuoso's overscan prop is removed; the new preload window replaces it.
  • The per-row useLoadEntry hook and its useEffect per row are gone; rows now just consume getEntry(virtualizedIndex) from the shared loader.

Verification

  • npm run check-types, npm run check-lint, npm run check-format, npm run test, and npm run build all pass.
Open in Web Open in Cursor 

Replaces per-row useLoadEntry with a single batched loader hook attached
to the LogView Body. The loader watches Virtuoso's itemsRendered
callback to track the visible range and:

- Triggers a load when the visible range comes within 50 rows of the
  cached range's edges (or has no cache yet).
- Eagerly fetches PRELOAD_DISTANCE (200) rows on each side of the
  visible range in a single getEntries() call.
- Discards in-memory data outside that window after each load.
- Throttles to one in-flight request at a time. If the visible range
  shifts during a load, a follow-up request fires as soon as the
  in-flight one settles, so the cache eventually catches up after fast
  scrolling. Later queries clobber earlier ones.
- Avoids race conditions: the loader is held in component state and is
  swapped (and the old one disposed) synchronously when logSearcher or
  entryNumbers change. The cache is cleared in the same render, so
  data from a previous filter set is never displayed even briefly.

Removes Virtuoso's overscan since this preload window replaces it.

Co-authored-by: Max Marrone <SyntaxColoring@users.noreply.github.com>
@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying log-viewer with  Cloudflare Pages  Cloudflare Pages

Latest commit: 4d42466
Status: ✅  Deploy successful!
Preview URL: https://a9ccbfe1.log-viewer.pages.dev
Branch Preview URL: https://cursor-batched-row-loading-8.log-viewer.pages.dev

View logs

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