refactor(query): extract QueryEntry.supersede — one owner for the reset contract#155
Merged
Conversation
…et contract The "invalidate this entry's in-flight world" transition (force stale, generation bump, cancel, retry reset) was written longhand in forceStaleAndRefetch and setQueryData, and they had already drifted: setQueryData cleared entry.error while forceStaleAndRefetch did not — despite setQueryData's comment claiming to mirror it. So invalidating an errored entry kept the stale error visible through the refetch, while the identical supersede via an optimistic write cleared it. Same sibling-inconsistency shape as Part I's diff arms. Both sites now route through QueryEntry.supersede(clearError:), making the one real difference a deliberate, documented, test-pinned decision: - invalidate → clearError: false. No new truth yet — keep the last-known error visible alongside the last-known data (SWR) until the refetch settles and overwrites both. The error persists until proven otherwise. - setQueryData → clearError: true. The optimistic write IS the new truth; a lingering error would contradict it. commitFetch's success path shares only the retry-reset half — it IS the committing fetch, so there is nothing to bump or cancel — and now calls the extracted resetRetryCycle(). Behavior-preserving: both policy tests were written and run GREEN against the longhand code before the extraction, so they pin today's semantics, not the refactor's. A third test pins supersede's full field-by-field contract. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
📦 Bundle size
✅ Within budget (≤5% growth allowed). Baseline: Swift 6.3, WASM SDK 6.3-RELEASE, measured 2026-06-18. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part II Wave 1 · #2 — the reset contract had already drifted
The "invalidate this entry's in-flight world" transition (force stale, generation bump, cancel in-flight, retry reset) was written longhand in two places — and they had already diverged:
setQueryDataclearedentry.errorforceStaleAndRefetchdid not — despitesetQueryData's comment claiming to "mirror" itSo invalidating an entry that held an error kept the stale error visible in snapshots throughout the refetch, while the identical supersede via an optimistic write cleared it. Same sibling-inconsistency shape as Part I #1's diff arms — the dominant defect class per the pre-launch audit.
Change
Both sites now route through one owner,
QueryEntry.supersede(clearError:)(QueryEntry.swift), so the transition can't drift apart again. The one real difference between the callers becomes a deliberate, documented, test-pinned decision:clearErrorforceStaleAndRefetch(invalidate)falsesetQueryData(optimistic write)truecommitFetch's success path shares only the retry-reset half — it is the committing fetch, so there's nothing to bump or cancel — and now calls the extractedresetRetryCycle()(also used insidesupersede).Behavior-preserving, provably
The two policy tests were written and run GREEN against the longhand code first, then the extraction happened under them — they pin today's semantics, not the refactor's. A third test pins
supersede's full field-by-field contract (generation bump, in-flight cancel, forced-stale, retry-ladder void, error policy both ways).Verification
QueryEntry/supersedesuite: 3/3🤖 Generated with Claude Code