apollo-client: "Store reset while query was in flight(not completed in link chain)" when stopQuery is called right after resetStore. Race condition?
Currently, queries are getting stuck in the QueryManager.fetchQueryPromises
Map when stopQuery
is called while that query is in flight.
Inside QueryManager.fetchQuery
a subscription is added to the QueryInfo
(QueryManager.query
object) of the Observable representing the current request.
this.setQuery(queryId, ({ subscriptions }) => ({
subscriptions: subscriptions.concat([subscription]),
}));
On the subscription, callbacks are set up to remove the queryId
from QueryManager.fetchQueryPromises
error: (error: ApolloError) => {
this.removeFetchQueryPromise(requestId);
// ...
},
complete: () => {
this.removeFetchQueryPromise(requestId);
// ...
},
When stopQuery()
is called before this query resolves, the promise will stay in that map because the subscription has been removed, therefore the callbacks to remove it will no long trigger.
public stopQuery(queryId: string) {
this.stopQueryInStore(queryId);
this.removeQuery(queryId);
}
public removeQuery(queryId: string) {
const { subscriptions } = this.getQuery(queryId);
// teardown all links
subscriptions.forEach(x => x.unsubscribe());
this.queries.delete(queryId);
}
Later on, this will cause problems when one tries to call resetStore()
public resetStore(): Promise<ApolloQueryResult<any>[]> {
return this.clearStore().then(() => {
return this.reFetchObservableQueries();
});
}
public clearStore(): Promise<void> {
this.fetchQueryPromises.forEach(({ reject }) => {
reject(
new Error(
'Store reset while query was in flight(not completed in link chain)',
),
);
});
// ...
}
Error: Network error: Store reset while query was in flight(not completed in link chain)
at new ApolloError (bundle.umd.js:124)
Intended outcome: I think queries should be removed from that Map after subscriptions get removed.
So as a solution, I might suggest that as part of the clean up for stopQuery, that the requestId
should be removed from QueryManager.fetchQueryPromises
. Perhaps there is a cancel method to evoke, or I should reject the promise with a new Error that the query has been cancelled.
Actual outcome: Queries are staying in that Map.
How to reproduce the issue: It’s an edge case, but this is how I ran into this issue through react-apollo:
- Render a Query wrapped component.
- Call
resetStore()
via user interaction - Immediately trigger a state change that results in that Query component being unmounted.
Versions
apollo-client: 2.3.5
react-apollo: 2.1.9
In hindsight I should have just written a PR instead.
About this issue
- Original URL
- State: closed
- Created 6 years ago
- Comments: 18 (7 by maintainers)
Can confirm this is still an issue
If somebody has still this issue… I resolved it with
stop()
beforeclearStore()
I don’t understand how this issue is closed while it is still there and happening. And in my case neither
client.cache.reset();
norclient.stop()
helps.I wonder if someone could verify whether this is a good minimal reproduction of this bug?
https://codesandbox.io/s/rj3w4vm4xo
The significant bit:
Console output:
It doesn’t seem to matter how long the timeout is, whenever the 2nd
resetStore
is called, the firstresetStore
’s promise finally throws an exception@chris-guidry Fixed! It was also a server issue🤦🏻♂️
I’m also seeing this problem. Any fix yet? It definitely seems to be a race condition - if I add a timeout between logout and resetStore then this error goes away. It seems like as long as there’s one more render between the logout and the resetStore then the error goes away. This is for an
@client
local query by the way.Hi, will this issue be resolved soon? Is there a workaround?