Skip to content

refactor(data): separate query lifetimes and guard async publication - #764

Merged
smiggleworth merged 1 commit into
developfrom
refactor/050-query-lifetimes
Oct 9, 2026
Merged

smiggleworth merged 1 commit into
developfrom
refactor/050-query-lifetimes

Conversation

@smiggleworth

Copy link
Copy Markdown
Contributor

QueryCell combines reader definitions/cache retention with fetch generations, queued promise admission, reconciliation and state publication. Move reader slots, definition conflict checks/promotion, cache identity and timers into private QueryLifetime. QueryCell retains one generation/controller publication authority and invokes lifetime transitions through an explicit capability contract. The transition table covers initial/manual/invalidation/reconcile work, abort, reader handoff/reattachment, GC, ownerless handles and SSR. Public query contracts remain unchanged.

The transition probes reproduce six original-source failures across five paths:

  • A consistency callback invalidates its own query, yet its obsolete consistent or inconsistent result replaces the retained snapshot.
  • A callback error publishes after its replacement work is canceled.
  • A predecessor's abort listener creates newer invalidation work, yet the obsolete start still calls transport.
  • A reconciliation abort listener invalidates, then the old retry replaces that newer work and suppresses its next retry.
  • An immediate-destruction abort listener mounts a reader for the same key and receives the destroyed cell still present in cache.

Capture/check one operation pair at each publication, recheck authority across user/abort callbacks, install the new controller before predecessor abort listeners run, and retire a destroyed cache identity before its abort callbacks. Eight new cases retain the succeeding operation's result/signal and prove both zero-retention replacement and retained-cache reattachment, late result rejection, refresh usability and final eviction.

Validation:

  • Original source at c973ad0: five unit failures plus one jsdom failure; two characterization cases already pass. The extraction initially retains the original failures; fixes make all eight cases green.
  • Before extraction: 55 data unit and 230 operations/owned-query/testing cases pass. After fixes: 61 data unit and 232 corresponding jsdom cases pass (including the two added transition cases).
  • Complete Node 24.21.0 npm run check: 439 unit, 94 repository, 2,695 jsdom, 158 browser and 12 installed type fixtures; formatting, lint, build, public types, publint and artifact checks pass. Full validation was repeated after changing destruction order; final formatting/diff checks pass.
  • Architecture guards test static/re-export/dynamic dependencies and keep the lifetime module independent of async state/publication. Six copied reader/definition method bodies remain identical; adapters retain lifecycle order except the tested destruction-cache fix.
  • Three alternating query dedupe/key-switch/abort captures per phase, all invariants and positive finite samples: before means 0.048040/0.048610/0.047877 ms; after 0.048953/0.048854/0.048412 ms. Median +1.7%, with 12,257–12,533 samples per capture; no speedup or broader performance claim.
  • Dated readiness records host-prop PR refactor(renderer): separate prop lifetimes and value writers #763 and its successful merge-head CI/CodeQL. Forty release issues remain at this pre-merge snapshot. No package versions, tags or publications change.

Closes #740.

@smiggleworth
smiggleworth merged commit e31d344 into develop Oct 9, 2026
4 checks passed
@smiggleworth
smiggleworth deleted the refactor/050-query-lifetimes branch October 9, 2026 17:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

refactor(data): make QueryCell ownership and async state boundaries explicit

1 participant