Repository navigation
feat(signals): report what each drain showed, and slim the observe hooks - #4725
devagrawal09 wants to merge 11 commits into
Conversation
Co-authored-by: tembo[bot] <208362400+tembo-io[bot]@users.noreply.github.com>
Co-authored-by: tembo[bot] <208362400+tembo-io[bot]@users.noreply.github.com>
Co-authored-by: tembo[bot] <208362400+tembo-io[bot]@users.noreply.github.com>
Co-authored-by: tembo[bot] <208362400+tembo-io[bot]@users.noreply.github.com>
Co-authored-by: tembo[bot] <208362400+tembo-io[bot]@users.noreply.github.com>
Co-authored-by: tembo[bot] <208362400+tembo-io[bot]@users.noreply.github.com>
Co-authored-by: tembo[bot] <208362400+tembo-io[bot]@users.noreply.github.com>
🦋 Changeset detectedLatest commit: 09462b3 The changes in this PR will be included in the next version bump. This PR includes changesets to release 15 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
Co-authored-by: Dev <devagrawal09@gmail.com>
Merging this PR will degrade performance by 2.71%1 warning
Warning Please fix the performance issues or acknowledge them on CodSpeed. Performance Changes
Tip Investigate this regression by commenting Comparing Footnotes
|
Co-authored-by: tembo[bot] <208362400+tembo-io[bot]@users.noreply.github.com>
…ched Co-authored-by: tembo[bot] <208362400+tembo-io[bot]@users.noreply.github.com>
Co-authored-by: tembo[bot] <208362400+tembo-io[bot]@users.noreply.github.com>
Summary
Today the core reports what ran and what was written to the attribution engine, but never what became visible. So the engine reconstructs visibility itself: it keeps a copy of the scheduler's staging state for fallbacks, snapshots nodes to tell whether async landings committed, and core computes diagnostic-only facts (the store's immutable-update census) on the engine's behalf.
This PR has core report one more fact, where a value was staged (
staged, fromqueuePendingNodeandlist). The engine compares what each staged node showed before and after each drain. On top of that comparison:FlushEvent.changeslists what each drain changed on screen: one entry per signal, memo or store property whose shown value differs from before the drain. That covers commits, held transitions' landings, and optimistic values appearing or lifting. Each entry carriesnodeId,nodeName,keyfor store properties, andorigin. The origin is the action step, effect, interaction or navigation that staged the value, so the drain that lands an action names that action. Nodes and values travel beside the record (FlushLive), and values only for listeners that asked for{ bodies: true }. Motivation: exact, action-attributed steps for time travel and state-history devtools (solid-kit).OPTIMISTIC_REVERTEDand thefallbackrecord's display instant are judged from the same comparison.With that in place, the hooks shrink to what core knows:
optimisticReverted(el, shown, truth, how)recomputeEnd(el, create, changed, optimistic, transition, held)+derivedChanged(el)recomputeEnd(el, create, changed, phase, held)asyncStart(el)+asyncEnd(el, prev, value, direct); the engine snapshots_value/_time/change seq; setSignal landings stamped twiceasyncLanded(el, value, changed), reported oncestoreReplaced(path, isArray, total, unchanged, prevTotal, owner); census computed instore.tsstoreWrite(target, old, written, keys); census in the engine, through theStoreToolsthe store registers at its init (the engine never imports the store)boundaryFallback(…, transition); engine copystagedFallbacks, rebased on settle/merge; coreschedule()s a drain for the engineboundaryFallback(…, output); displayed when the comparison sees the output changeDEV.hooks.onUpdate,DEV.hooks.onStoreNodeUpdateflushrecord covers both (observe/dev,attribution.enable())staged(el)Size
The size gate (
scripts/size, CI'scheckjob), head against this PR's base (next@701cbb36), minified / brotli bytes:dist/prod)DEVimport)store.ts−75,lanes.ts−13,boundaries.ts−10;core.ts+31,attribution-hooks.ts+11 forStoreTools), engine +175¹ For each hook, the product of the distinct values of every input a consumer branches on (booleans 2, literal unions their size, meaningful optional inputs +1), summed over
AttributionHooks+DEV.hooks.An earlier revision had the engine import
store/store.tsfor the census, which pulled the store into the engine scenario for an app without stores (+19.5 kB minified) and failed the gate. The store now registersStoreToolsat its init and the engine reads through them, so nothing undercore/importsstore/.For review
DEV.hooks.onUpdateandonStoreNodeUpdatebreaks existing users (devtools). They're independent of the rest and can stay if you'd rather. Store properties nobody reads have no node, so they're not inflush.changes.revertedvssupersededis decided by identity against the covered value. A fallback mounted outside any drain is displayed as the mount returns (before: at the drain core scheduled for it).flushEndcould follow the same route, but it would change what "settled" means, so I left it for a separate discussion.How did you test this change?
packages/signals/tests/attribution-flush-changes.test.ts(7 tests): changed signals and memos are listed with their origin; one record per drain; values only withbodies, beside the record; store keys; a held write listed at its landing, naming its action; an optimistic value listed when it appears and when it lifts; effects and first values not listed.OPTIMISTIC_REVERTED(8), the fallback and timeline records (attribution-timeline,loading-fallback-in-flush-3540and the other fallback suites), immutable updates, holds, interactions.onUpdate/onStoreNodeUpdatetests (signalsdev.test.ts, soliddev.spec.ts). TheDEV.setSignalstore test now asserts the reader re-runs.pnpm turbo run test test-types typecheckacross packages: signals 6,749, solid-js 927, diagnostics 37, element 10, html 209, h 72, universal 57, babel-plugin 422; web client 1,747 and hydrate 758 (run directly). Web server suite: one failure,server-functions-adapter-request.spec.tsx› "keeps a rebuild failure's own error…", which fails the same way onnextwithout this change.landThroughSetSignalsaves and restores its re-entrancy state instead of resetting it;trackStagedwalks for an origin only once a node is watched (it runs on every write while the engine is enabled); the docs sayflush.changescompares by identity and that a fallback rendering the value already shown is no record.next(built both and diffed), so that is instrument noise.pnpm build(17/17 packages);dist-artifactspass;dist/proddiffed againstnext(no code change);generate-diagnostics-json --checkup to date; prettier clean. Changeset:.changeset/flush-record-changes.md.