oxidecomputer / oxidecomputer/console

Everything-up-front pagination

Open
#2,029 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
TypeScript
Stars
228
Forks
22
Avg merge
19h 42m
Merged PRs (30d)
32

Description

There are annoyances we can't fix in the current implementation like the fact that if you go to the next page of results in the console and refresh the page, you'll land back on the first page of results because the page is not represented in the URL (#1102). We have long thought we were blocked on improving pagination UX by Dropshot limitations like the lack of a way to paginate backwards (https://github.com/oxidecomputer/dropshot/issues/436). However, after @ahl explained to me that the intent with that design was that the client would fetch approximately everything up front and handle pagination itself, my mind was opened to a world of possibilities that are frankly very cool.

The default page size in Dropshot is 100, and the max is 10000 (source). Nexus does not override these defaults.

let server_config = ServerConfig {
    // We start aggressively to ensure test coverage.
    request_body_max_bytes: config.request_body_max_bytes,
    page_max_nitems: NonZeroU32::new(10000).unwrap(),
    page_default_nitems: NonZeroU32::new(100).unwrap(),
    default_handler_task_mode: config.default_handler_task_mode,
};

In general, we tend to think that 1000 is a rough upper bound for how many items can expect to get in any list of things. You can make more than that of some resources, but you really have to try. If instead of pulling one page at a time from the API, we fetched everything we can find, there would be numerous advantages:

  • Changing pages would be instant
  • We can do arbitrarily complex yet still instantaneous search and filtering client-side
  • We can invent whatever query string page param scheme we want, if we still want one when search and filtering is so good

The obvious first objection is that fetching 400 things is probably slower than fetching the first 25, we would delay initial page load. Now, I'm not sure yet whether that's true enough for us to care, and it may be that we can get a lot of mileage out of fetching a huge page without getting clever. We might even be better off implementing gzip on the API side (https://github.com/oxidecomputer/dropshot/issues/221) than we are getting clever on the client — JSON bodies have a ton of repetition and probably compress really well.

If we want to do this well, we should also address some long-standing pain points, like the fact that you have to manually make sure you are fetching the right number of things in the loader to match what QueryTable does automatically. I have been lamenting recently that we do quite bit of work fighting the way the paginated endpoints are handled in the client generator. I have a hunch there is a smart abstraction that would be easy to build on the generation side that would save a lot of work on the app side.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reading the pagination handling in app/pages/ProjectsPage.tsx, app/api/hooks.ts, and app/table/QueryTable.tsx, then review the linked Dropshot pagination constraints. Define the client-side pagination and loading approach before implementing it; done should include a consistent data-fetching abstraction and a clear decision on URL state, filtering, and initial-load behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
frontend
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.