refactor: migrate remaining remote-view pages to useRemoteView() and shared isFirstLoad/isUnreachable flags - #506
refactor: migrate remaining remote-view pages to useRemoteView() and shared isFirstLoad/isUnreachable flags#506jbouder wants to merge 7 commits into
Conversation
…shared isFirstLoad/isUnreachable flags.
✅ Deploy Preview for nebi-docs canceled.
|
Refetching a never-succeeded query resets it to pending and clears isError, so the unreachable banner flashed off (and the empty state on) for the duration of every failed retry against a down server. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Architecture ReviewInferred Patterns
Blockers (design-gating)[D] AGENTS.md now overclaims the flag pattern the codebase actually satisfies
Questions[D] Should the migrated banner pages also get the self-heal polling half of the pattern?
[D] Was leaving the
|
…e AGENTS.md invariant Review follow-ups on #506: - Add retryWhileUnreachable and wire it into the four banner-feeding queries that don't poll (registries, users, admin registries, audit logs): an errored query with no refetchInterval only refetches on remount or focus, so the banner added in this PR would stick after the server recovered. Healthy-state behavior is unchanged (still no polling) — steady-state freshness polling stays a product decision per #504. - Document the banner/retry coupling on withRemoteFlags, and split the useRemoteView comment back onto its own declaration. - Restore a scoping caveat to the AGENTS.md invariant: RemoteWorkspaceDetail.tsx and the per-workspace hooks are not yet migrated, tracked in #507. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Thanks for the thorough review @tylerpotts — addressed in 5a4ada6: Blocker (AGENTS.md overclaim): Restored a scoping caveat to the "Two frontend invariants" bullet — Stuck banner on the no-poll queries: Agreed this recreated the exact condition the
"refactor:" title vs behavior: Yes — the banner-hold semantics from f9a7a4f applying to the previously-migrated pages is intended; the flash-off-during-retry was the same defect everywhere, and centralizing the fix in Stylistic: Split the comment blocks so |
go1.26.5 has 8 known-fixed stdlib vulnerabilities, all patched in go1.26.6, which fail both the govulncheck gates (Backend / Security, Build, Build CLI Binaries) and the Trivy image scan: GO-2026-6218 / CVE-2026-56860 net/url quadratic path parsing DoS GO-2026-6091 / CVE-2026-56858 html/template XSS on pathological input GO-2026-6090 / CVE-2026-56862 crypto/tls indefinite KeyUpdate DoS GO-2026-6089 / CVE-2026-56853 net/http unencrypted HTTP/2 DoS GO-2026-6088 / CVE-2026-56859 encoding/xml decode recursion DoS GO-2026-5972 / CVE-2026-33818 encoding/asn1 Unmarshal recursion DoS GO-2026-5942 / CVE-2026-46600 dnsmessage SVCB/HTTPS RR parse panic GO-2026-5026 / CVE-2026-39821 x/net/idna ASCII-only Punycode labels Bumps the go.mod toolchain directive (which every workflow resolves via go-version-file) and the pinned golang image + digest in the Dockerfile, keeping the two in sync as check-go-toolchain.sh requires.
Architecture Review (round 2)Scope: No blockers. One substantive finding worth fixing here, two small notes. Round-1 items: all three resolved
The flag logic is correct (I checked, rather than assumed)I went in suspecting the
Checked specifically as well: every migrated page scopes the banner as Finding: the
|
tylerpotts
left a comment
There was a problem hiding this comment.
Some optional fixes that would be worth doing in this PR described above, but not blocking if you decide to leave them alone
The `{...query}` spread in withRemoteFlags reads every own property of the
result, and with notifyOnChangeProps unset useQuery returns TanStack's
tracked-props proxy, whose get trap marks each read property tracked. So the
wrapper marked isFetching/fetchStatus/dataUpdatedAt tracked and re-rendered
every consumer on each poll tick, even when the payload was referentially
unchanged — a regression against the pre-migration shape, where pages
destructured only data/isLoading/isError/errorUpdateCount.
Pins notifyOnChangeProps once, next to withRemoteFlags, to exactly the fields
the flags and pages read; useBaseQuery then returns the raw result and the
spread costs nothing. Adds a render-count test on useRemoteWorkspaces (fails
at 3 renders without the pin, passes at 2 with it).
Also corrects the "remount or window focus" parenthetical in the coupling
comments and AGENTS.md: refetchOnWindowFocus is false app-wide, so remount is
the only recovery path for an errored query with no interval.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Thanks for round 2 @tylerpotts — the
which matches your numbers. Fixed as you suggested: a shared Also added the render-count assertion you called for ( Comment accuracy: fixed in the same commit. Both Type narrowing: noted, no change here — nothing relies on it today. I've added it to #507 so whoever wraps the detail hooks knows the union collapses before they reach for
|
Closes #504.
Summary
withRemoteFlagshelper inuseRemote.tsthat wraps every remote list query and returns namedisFirstLoad/isUnreachableflags, so pages consume intent instead of re-deriving gating from TanStack internals (errorUpdateCount). The issue-Bug: White screen flash every ~5s when configured remote server is unreachable #217 retry-flash rationale now lives once, in the hook.Registries,admin/UserManagement,admin/AuditLogs,admin/RegistryManagement— touseRemoteView(), each now showingRemoteUnreachableBannerwhen the remote is down in remote view, with the same first-load spinner gating Workspaces/Jobs/AdminDashboard got in Fix: White screen flash every ~5s when configured remote server is unreachable #501. Their empty states are gated behind!remoteUnreachableso a down server doesn't read as an empty list.errorUpdateCountchecks.LayouttouseRemoteView()(which subscribes to the sameremote/serverquery internally, preserving the never-unmounting self-heal observer) with a comment explaining that role.useRemoteView()".isFirstLoadlifecycle and the errored →isUnreachabletransition; updates theRegistryManagementtest mock.Out of scope (per the issue): the no-interval queries keep their current no-polling behavior; no backend changes to
/remote/serverstatus semantics.Test plan
npm run test— 201 passednpm run check— cleannpm run build— passes🤖 Generated with Claude Code