Cluster card refreshes itself while a cluster is provisioning¶
Motivation¶
After clicking Start on a stopped AKS cluster from the dashboard (and not
navigating away), the cluster row stayed on Starting… indefinitely and only a
manual page reload showed the settled state. The Start action felt broken even
though the cluster had already started.
Root cause: the row's Starting… label is an optimistic transition chip
held in localStorage, not the backend provisioning_state. The chip is only
cleared once a poll observes the settled power_state=Running +
provisioning_state=Succeeded (transitionTargetReached). Chip removal
therefore depends entirely on the cluster-list useQuery actually refetching
fresh data. Two gaps starved that refetch:
- The global
QueryClientdefaults (refetchIntervalInBackground: false,refetchOnWindowFocus: false) stop polling when the tab is backgrounded and never refetch on focus return. - Even in the foreground, the base poll runs at the user's auto-refresh cadence (30–60 s) and the backend monitor snapshot cache (30 s) could serve a stale pre-settle snapshot, so the chip could persist far longer than the actual Azure transition.
A manual reload remounts the query and fetches immediately, which is why only a refresh appeared to work.
User-facing change¶
While any cluster is provisioning (ARM provisioning_state in
Creating/Starting/Stopping/Updating/Deleting) or a live in-browser
start/stop/delete transition is tracked, the AKS cluster card now:
- polls every 5 s (capped below the user's chosen auto-refresh) instead of the idle 30–60 s cadence;
- keeps polling when the tab is backgrounded and refetches the moment the tab regains focus;
- asks the backend to bypass its 30 s monitor cache (
fresh=true) on every poll — now extended to cover provisioning clusters started outside this browser (portal / CLI), which previously had no local transition record.
Once everything settles, the card automatically returns to the idle posture (user's auto-refresh cadence, no background refetch, normal caching) — so idle dashboards keep the calm, cost-minimised polling behaviour with no extra background traffic.
API / code change summary¶
web/src/components/cards/ClusterCard/ClusterCard.tsx:- Added an
activePollingstate (seeded from the persisted-transition store) plus anactivePollingRefmirror so the stablequeryFnclosure reads the current hot state at call time. - An effect drives
activePollingfromhasProvisioningCluster || actions.transitioning.size > 0. - While hot:
refetchIntervalis clamped tomin(base, 5_000),refetchIntervalInBackground/refetchOnWindowFocusare enabled,staleTimeis0, and thefreshquery flag is OR'd withactivePollingRef.current. - Idle behaviour is unchanged (base interval, no background refetch, default
stale time,
freshonly when a local transition exists).
No backend, API contract, or IaC change. No new dependency.
Validation¶
cd web && npx tsc(via editor): no type errors in the changed file.npx eslint src/components/cards/ClusterCard/ClusterCard.tsx: clean.npx vitest run src/components/cards/ClusterCard src/utils/aksStatus.test.ts: 21 passed.- Diff isolated to
ClusterCard.tsx(verified withgit diff --stat).