Repository navigation
(core) - Refetch queries invalidated while their request is in flight - #3925
Open
Karanvir1729 wants to merge 1 commit into
Open
Karanvir1729 wants to merge 1 commit into
Karanvir1729 wants to merge 1 commit into
Conversation
A mutation or subscription result that invalidates a typename while a query with that typename has a request in flight could fail to refetch the query: the client deduplicated the reexecute, or the document cache had no entry for the query yet. The in-flight answer was then cached and delivered as fresh even though it may predate the mutation. cacheExchange now records the typenames invalidated during a query's request. If the request's last result has one of them, the result isn't cached, is marked as stale, and the query is reexecuted as network-only. The client's deduplication is unchanged.
🦋 Changeset detectedLatest commit: 1387ec5 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
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 |
3 of 10 tasks
This branch has not been deployed
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.
Refs #3157, #3912. No issue is open for this.
Summary
When a mutation result invalidates a typename while a query with that typename has a request in flight, the default
cacheExchangecan fail to refetch the query. The in-flight answer, which may predate the mutation, is then cached and delivered withstale: false, and the app stays on it until the next invalidation.Two paths lead there:
cacheExchangedeletes it and callsreexecuteOperation, and the client drops that operation if the key is still indispatched(nextOperationinpackages/core/src/client.ts). That deduplication is deliberate (fix(core): Strictly deduplicate operations for cache-and-network and network-only #3157), so this PR leaves it alone.operationCachehas no entry for it, so the invalidation skips it. This covers two mutations close together, where the second lands during the refetch caused by the first.Measured at f57b089 with a real
Client,cacheExchangeandfetchExchangeover a fakedfetchthat computes each answer when the request arrives and holds query answers. Each row gave the same outcome in 3 of 3 runs before and 3 of 3 after. The server ends at v2, except where noted.cache-firstread gives v1cache-and-network's requestnetwork-onlyquery merged into an identical one in flight, sent after the mutationSet of changes
packages/core/src/exchanges/cache.ts: records the typenames invalidated while each query's request is in flight. If the request's last result has one of them, the result isn't cached, is markedstale: true, and the query is reexecuted asnetwork-only. This is the pattern fix(graphcache): Deduplicate cache misses of in-flight operations #3912 uses in Graphcache for subscription results. The client's deduplication is unchanged, so merged queries still share one request at a time.packages/core/src/exchanges/cache.test.ts: 13 tests with a realClientand a network exchange the test answers by hand, with no timers, so they can't pass on timing. They include the failure paths: a failed query, a failed mutation, an older request failing after a newer one answered, a mutation with no matching typename, teardown, and incremental results.@urql/core. Not breaking.Behaviour worth checking:
toPromise()on such a query now resolves with the refetch's result, or its error if the refetch fails.dispatched. That is where the extra request in the last two rows comes from. In that case an older answer can show briefly withstale: falsebefore the refetch answers, and if the oldest request answers or fails after the refetch too, it still wins, as it does today. One of the two failing also clears the tracking for the other, so a mutation during the rest of that request is missed. Cancelling superseded requests infetchExchangewould close these; it is left out of this change.additionalTypenameson a subscription counts as an invalidation here, as it already does for cached results. A steady stream of such events refetches back to back, one request at a time, withstaleset until a request completes with no event during it, andtoPromise()stays pending that long. Before this change it resolved on the first answer.Checks:
vitest run packages/core/src/exchanges/cache.test.ts: without thecache.tschange 8 of 22 fail, 3 of 3 runs; with it all 22 pass, 3 of 3 runs. The other 5 new tests are controls that pass either way.vitest run packages/core: 19 files, 202 tests pass, 3 of 3 runs.vitest run packages/react-urql/src: 10 files, 55 tests pass, 1 run.tsc --noEmitinpackages/coreare clean. Breaking any one of 11 parts of the change, one at a time, makes at least one test fail.@urql/coreandurqlwere installed), the Cypress tests, the builds, and rootpnpm run check.AI assistance: Claude (Claude Code) investigated this, wrote the fix and the tests, ran the checks above, and drafted this description. I have not run them or reviewed the change by hand yet.