Files
multica/packages
Naiyuan Qing b06c489413 fix(issues): stabilize the Table query identity so a workspace switch cannot churn its branch queries (MUL-5477) (#6178)
Switching workspaces onto a persisted Table + hierarchy surface pinned the
renderer at ~150% CPU. Three reference-stability defects on that path, all in
the window where the surface's own queries have not settled yet — which is
exactly the window a workspace switch opens:

- `tableQuerySpec` is built from 17 dependencies and two of them defaulted their
  un-settled data to a fresh `[]`, so every render produced a new-but-identical
  spec. Every consumer keys off that identity: the facet request, the status and
  group branch hooks, and the Table's `useQueries` branch list, which was
  rebuilt once per render for a query that had not changed.
- Each rebuilt branch query carried `placeholderData: () => placeholder`.
  QueryObserver reuses a placeholder result only while that option compares
  equal by reference, so a fresh arrow per render forced the placeholder to be
  recomputed and the result re-derived every time.

The fixes are the smallest ones that remove those edges rather than damp them:
the two empty defaults become one module-level constant (the same pattern
`useActorName` already uses for its own lists), the spec's identity is pinned to
its content with TanStack's own `hashKey` so it agrees with how the same spec is
hashed into a queryKey, and the placeholder is passed as the value it always
was. `useMemo` rather than a render-phase ref write, so nothing mutates during
render.

This removes feedback edges on the reported path. It is NOT a confirmed root
cause for the production hang: the loop has not been reproduced against the
affected client, and acceptance is still a live check on that machine.

Regression coverage closes a real gap. Production mounts the Table with
`virtualizeRows` and hierarchy on, and no test covered that combination —
every existing one replaces the virtualizer, because jsdom reports a
zero-height viewport. The new test supplies the layout instead, so the real
measuring virtualizer sits in the circuit, and asserts the table stops
committing once the tree settles. That circuit is load-bearing: while writing
the test, an unstable mock closure alone reproduced a sustained ~35 commits/s
storm with no fetching and no DOM measurement, which is why the mocks there
return hoisted references and why the convergence assertion needs the real
virtualizer to mean anything.

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Co-authored-by: multica-agent <github@multica.ai>
2026-07-30 16:26:42 +08:00
..