Conversation
Code ReviewOverviewThis PR improves the onboarding flow in the namespace route loader and related frontend infrastructure. The changes look well-structured, but there are a few issues worth addressing. Bugs1. Inverted undefined guard silently suppresses onboarding (
namespace !== undefined && namespace.displayName !== "Default"2.
const hasRunnerNames = pages.some(p => p.runners.length > 0);Minor Issues3.
4. 24-hour If a user deleted all runner configs and revisits within 24 hours, the cached stale data causes the cache-first gate to skip the fetch, showing no onboarding until the background refetch fires. A shorter SummaryThe two bug-level issues (#1 and #2) are the most actionable — both can cause the onboarding flow to be incorrectly suppressed in real production scenarios. The minor issues are lower priority but worth a follow-up. |
…pace, improve caching
7c3c044 to
3a1e78a
Compare
| const namespace = await context.queryClient.fetchQuery( | ||
| context.dataProvider.currentNamespaceQueryOptions(), | ||
| ); | ||
| if (namespace?.displayName !== "Default") { |
There was a problem hiding this comment.
Bug: the undefined-namespace guard is inverted. When the API returns an empty list, namespaceQueryOptions returns data.namespaces[0] which is undefined. Then namespace?.displayName is undefined, and undefined !== 'Default' is true, so the loader exits early with displayOnboarding: false — silently suppressing onboarding for a namespace whose state is unknown. The correct guard is: only skip onboarding when namespace is defined AND its displayName is not 'Default'. An unresolvable namespace should fall through to the onboarding fetch rather than hiding it.
| ) | ||
| .find((p) => p !== undefined); | ||
|
|
||
| const hasRunnerNames = (runnerNames?.pages[0]?.names.length ?? 0) > 0; |
There was a problem hiding this comment.
Bug: only pages[0] is checked but deriveOnboardingState scans all pages for the provider. When an infinite query spans more than one page, pages[0] could be empty while later pages hold names or configs, causing hasBackendConfigured to be false and incorrectly showing the onboarding screen. The provider lookup just above this line already correctly uses (runnerConfigs?.pages ?? []).flatMap — apply the same pattern here: runnerNames?.pages.some((p) => p.names.length > 0) and runnerConfigs?.pages.some((p) => Object.keys(p.runnerConfigs).length > 0).
| retry: shouldRetryAllExpect403, | ||
| meta: { | ||
| mightRequireAuth, | ||
| persist: true, |
There was a problem hiding this comment.
Bug: persist:true is attached to every invocation of runnerConfigsQueryOptions, including the variant-filtered call in all-runner-select.tsx (runnerConfigsQueryOptions({ variant: 'serverless' })). That call gets a different query key ([{namespace}, 'runners', 'configs', {variant:'serverless'}]) but still carries persist:true, so serverless-variant configs are also written to localStorage. The persist comment says only a curated allowlist should be stored. Fix: make persist conditional on the no-opts path: persist: opts === undefined.
|
|
||
| const persistOptions: Omit<PersistQueryClientOptions, "queryClient"> = { | ||
| persister: queryCachePersister, | ||
| maxAge: 24 * 60 * 60 * 1000, |
There was a problem hiding this comment.
PLAUSIBLE: a 24-hour maxAge creates a wide window where deleted configs appear to still exist. If a user removed all runner configs in a previous session, the persisted cache entry keeps showing hasBackendConfigured=true for up to 24 hours. On reload the cache-first gate skips the blocking fetch, deriveOnboardingState derives displayFrontendOnboarding=false (backend configured, no actors), and no onboarding is shown — until the background refetch fires and invalidates the loader, causing a flash. A 1-hour maxAge is sufficient to survive typical page refreshes while bounding the stale window.

Description
Please include a summary of the changes and the related issue. Please also include relevant motivation and context.
Type of change
How Has This Been Tested?
Please describe the tests that you ran to verify your changes.
Checklist: