Commit d40cc62
committed
fix: preserve fragment data identity across snapshot updates
`reconcile({ key: "__id", merge: true })` only preserves identity by
walking the existing tree in place when the current store value is
wrappable. solid-js/store's `reconcile` (modifiers.ts) early-returns
the new value as-is when it isn't, so reconciling against `undefined`
silently produces a fresh top-level reference and the merge contract
goes away.
The result observer was pre-clearing `data` to `undefined` inside the
same batch that subsequently applied the reconciled snapshot, so that
contract was being defeated on every Relay update. Identity-sensitive
consumers — most prominently `<Show keyed when={data()}>` — re-mounted
their subtree on every snapshot tick, including pure field updates
such as a reaction toggle or a polled count delta. In a real fediverse
timeline (hackers.pub `/feed`, ~25 cards × multiple Kobalte primitives
per card), this dominated CPU and heap during interaction (~+10 MB/s
sustained vs. ~0 MB/s when idle on the same route).
Restructure the observer so each branch owns its full state transition
and no shared pre-clears defeat the reconcile:
- "ok" — clear `error`, set `pending` to false, reconcile `data`.
- "error" — set `data` to `undefined`, set `error`, set `pending`.
- "loading" — no case. Leave `data` / `error` / `pending` as-is for
stale-while-revalidate behaviour, matching `createLazyLoadQuery`'s
observer in the same package.
Behaviour is otherwise unchanged. Observers never saw the intermediate
pre-clear state — every mutation is inside the same `batch()` — so the
fix is invisible to anything except identity comparisons across snapshot
boundaries, which the reconcile contract is exactly there to keep
stable.
Assisted-by: Claude Code:claude-opus-4-71 parent 1bfb1a9 commit d40cc62
1 file changed
Lines changed: 18 additions & 3 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
132 | 132 | | |
133 | 133 | | |
134 | 134 | | |
135 | | - | |
136 | | - | |
137 | | - | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
138 | 153 | | |
139 | 154 | | |
140 | 155 | | |
| |||
0 commit comments