Repository navigation
ui: look up sandboxes outside the loaded list by identifier - #1244
Conversation
|
Thanks for opening this pull request! A SPACE maintainer will take a look. CONTRIBUTING.md explains how we review outside contributions. |
The sandbox list loads the newest 1000 rows from the admin API once and filters them in the browser; the admin list has no cursor or search, so an older sandbox in a larger fleet could not be found by any search, and nothing said the list was cut off. A full identifier in the search box (the public ID, a bare or undashed UUID, or the sandbox pod name) now names one sandbox: it matches the row whatever the other filters say, and when no loaded row matches, the page fetches that sandbox directly and shows it with a notice. When the list is capped the page says so. "Load newest" chooses 100, 1000 or the API maximum of 5000 rows (also `?limit=` in the URL), and the overview's count reads "1000+" instead of a capped number. Server-side search, filters and paging still need admin API support; this keeps every sandbox reachable until then.
A sandbox found by direct lookup is now refetched on every list load, with at most one request per ID in flight. The row stays shown while it refreshes, a 404 clears it, and an answer for an ID the search box no longer names is dropped. The table shows as loading while the first lookup is pending. A load-size change during a lookup used to cancel it and leave an empty table with no message; the next list load now refetches it. The lifecycle policy dialog opens for a looked-up row. The admin list appends node-reported rows (rowless pool slots, observed-local sandboxes) after its `limit` sandbox rows, so only sandbox rows count toward "capped", on the list and on the overview. A list answer for a load size that has since changed is dropped, and a list larger than the default polls about every 15 seconds.
A looked-up ID with no row (a 404, or an error before any row was found) brought the table's loading spinner back on every list reload, because each refetch reset the pending state. The table now shows as loading only until the first answer for that ID. A list larger than the default used the refresh timestamp every console window shares, so a default-size list open in another window kept it "fresh" and it never reloaded, nor did its looked-up row. The larger list now keeps its own refresh timestamp.
9e65269 to
06814fc
Compare
Withdrawing this approval for now. Any feedback above still stands.
johnlouie-pplx
left a comment
There was a problem hiding this comment.
Approving at 06814fc, with one nonblocking ask. The direct lookup uses the existing authorized endpoint, and all 75 UI tests passed locally.
Could we give the lookup effect in sandboxes/page.tsx a per-request token and only let the current request update the result or clear the in-flight marker? I reproduced A → B → A with the real component and mocked responses: the first A request can finish last and overwrite the newer result, including replacing a valid row with “not found.” A regression test that completes those requests out of order would cover it. #1248 fixes the separate list-spinner issue, but not this lookup race. Worth fixing proactively here, though I wouldn't hold the merge for it.
Summary
Every sandbox can now be found from the sandbox list by its identifier, however large the fleet.
The list loads the newest 1000 sandboxes (
GET /admin/api/v1/sandboxes?limit=1000), reloads them periodically while the page is visible, and filters them in the browser. The admin list has no cursor and no search, and it orders bycreated_at DESC. In a fleet with more than 1000 live sandboxes, the oldest ones (often the long-running sandboxes a support case is about) were therefore not found by any search, and nothing on the page said the list was cut off.Changes:
sbx_ID, a bare or undashed UUID, and the pod namespace-sbx-<hex>-g<N>. The placeholder now reads "ID, pod name or name".GET /admin/api/v1/sandboxes/{id}and shows it with a notice. The table shows as loading only until the first answer for that ID; later refetches, including ones that answer 404, do not bring the spinner back. The row is fetched again after each list load, so it stays current after an action, a Refresh or a poll; it stays shown while that runs, and a 404 clears it. An unknown ID shows the API's "Sandbox not found".limitsandbox rows.?limit=. A list larger than the default reloads less often than the default-size list (at most about every 15 seconds), and keeps its own refresh timestamp: console windows share one per view, and a default-size list open in another window would otherwise keep the larger list from ever reloading. An answer for a load size that has since changed is dropped.1000+instead of a capped number, counting sandbox rows only.Partial text still filters the loaded rows by ID fragment or name.
Server-side search, filters and cursor paging need admin API work and are not part of this change. Until then, this keeps every sandbox reachable by ID.
Stack
Stacked on #1242, which adds
parseSandboxRef. Merge #1242 first. This branch is restacked on #1242's review follow-up. #1248 is stacked on this PR.Validation
npm ci,npm test(75 pass) andnpm run buildinui/. The new unit cases insrc/lib/sandbox-id.test.mjscover exact lookup in every form, ID fragments, names, the limit clamp and the sandbox-row count.mainwith this branch (the Kindspace-uiimage). It found no new console errors, page errors or failed requests.?limit=2: only the two newest sandboxes load, and searching the pod name of an older one finds it by direct lookup.Visual confirmation
With only the newest 2 sandboxes loaded, the pod name of an older sandbox finds it:
Video: after.
main): no matchSeverity and risk
Severity: high. Finding a sandbox by ID is the first step of most support cases, and it silently failed for any sandbox outside the newest 1000.
Risk: low.
GET /admin/api/v1/sandboxes/{id}on each list reload, never two at once for the same ID. Nothing extra is requested otherwise.AI assistance: Claude Code wrote the code, the tests and this description, and ran the validation; a maintainer reviews it.