-
Notifications
You must be signed in to change notification settings - Fork 746
Normalised Cache Not Using Data from Different Query #3345
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Hi @reubn – I took a quick look at your minimal test case, and I think that there's a bit of a mis-understanding of how the cache functions. Within your As you said, you're really looking for the Your fetch data function becomes something like this: func fetchData() {
GraphQL.shared.apollo.store.withinReadTransaction { transaction in
let countryInfo = try transaction.readObject(ofType: CountryInfo.self, withKey: "Country:\(code)")
self.country = countryInfo
}
} More important that having a fix (which may or may not work for your use-case) is understanding why what you're attempting to do fails. Imagine, for a moment, that your query CountryDetailQuery($code: ID!) {
country(code: $code) {
...CountryInfo
population
officialLanguage
currentLeader
governmentType
# etc
}
} At this point, there's a very clear divergence between the For example, a |
I'm closing this issue due to inactivity. If this is still unresolved, feel free to provide more information and we can re-open this, or create a new issue. |
Do you have any feedback for the maintainers? Please tell us by taking a one-minute survey. Your responses will help us understand Apollo iOS usage and allow us to serve you better. |
I'm experiencing the same issue. And reading the docs in https://www.apollographql.com/docs/ios/caching/introduction I was under the impression that "Normalizing objects by cache key" would make Apollo fetch from cache even when is a different query since it's asking for exactly the same info a previous query already cached with the right cache key to be the same identifier? |
@comontes That is how it should work generally. If you are not seeing the expected behavior, please open an issue with specific information about your use case. Preferably, including a reproduction case we can look at to help us assist you. |
We too have been bit by this on iOS, especially since I've come to expect this from the Kotlin Apollo client, which offers One area where it's a pain is when setting up watch queries globally: For a contrived example, say we have a query: query CurrentUserFilms {
id
title
rating
} which returns a list of Film objects, lets say. Then, we want to set up a global watch query to update the UI of an on-screen film when only the rating changes anywhere in the app: query FilmRatingById($id: ID!) {
node(id: $id) {
... on Film {
id
rating
}
}
} Making sure to set cachePolicy to What I've resorted to is to manually mutate the cache to write the Film data from The watch query is just one example, but it has other implications for |
Ohhh, I see now. I missed the point of this. You're talking about something akin to the That is on our current roadmap, but we haven't started development of the feature yet. |
Hi @AnthonyMDev — really appreciate your work on this library. I also ran into this limitation last week, and it genuinely caught me off guard — largely because my experience with Apollo on the web had led me to expect that normalized cache reuse would “just work” across related queries. After reading your note about @fieldPolicy being on the roadmap, I spent some time exploring a modest solution that could help bridge the gap in the meantime, particularly for common patterns like getEntityById after getEntities. RecapAs others on this thread have noted, Apollo iOS currently misses the cache for queries like: query CountryByCode($code: ID!) {
country(code: $code) {
...CountryFragment
}
} …even when the data already exists in the cache from a previous query like: query AllCountries {
countries {
...CountryFragment
}
} Because the CountryByCode query hasn’t been executed before, ApolloStore has no way of knowing there's a normalized object with the requested shape and identity from the AllCountries query. Proposed SolutionAs a stop-gap, add a simple, non-breaking hook to SchemaConfiguration: static func cacheResolverInfo<Operation: GraphQLOperation>(
for operation: Operation.Type,
variables: Operation.Variables?
) -> CacheResolverInfo? This hook allows library consumers to provide metadata that helps ApolloStore identify the target of an operation so it can attempt to resolve the result from existing cache data—even if it has never been executed. The returned CacheResolverInfo includes:
ApolloStore uses this to perform a targeted cache read and synthesize a valid GraphQLResult<Operation.Data>. If the object is missing or incomplete, it gracefully falls back to the default resolution strategy. Benefits
ImplementationI’ve published a working solution in a GitHub fork. The changes are small and thoroughly documented: Would your team be open to reviewing a PR for this? I’d be happy to tighten it up or align with any design considerations you have in mind. |
Thanks for all the work you've done on that! Our team would love to work with you on a PR for this feature, however this approach isn't going to work for us. Currently, this PR would only support fixing this issue for a single field within an operation. We should actually be focusing on allowing this to be configured for each field individually. Adding an additional configuration hook into the Once we have that mechanism in place, you could programmatically configure these, but it would also make adding the This is on our roadmap, but we have some other work that we are prioritizing right now, so no guarantees when we will get to it. If you would like to work on a PR for this though, we would be happy to support you through that process! |
Summary
I have a very simple use case that doesn't seem to be handled by the normalised cache properly.
I have a query that returns a list of
Country
s using aCountryInfo
fragment.I then have a second query that queries for a specific
Country
, returning the same fragment.The data returned for the first query populates the cache, but is not used for the second query. Apollo returns the following error.
I have set up custom cache keys, but Apollo seems to only correctly return cached data for the same query, despite the 2 pieces of data in the cache having the same cache key. This is unexpected.
By introspecting the
SQLiteNormalizedCache
database I can see that the data from the first query is stored and keyed correctly, but this not appear to be read in the second. The test case behaves identically with theInMemoryNormalizedCache
.I can see that a similar issue was reported #842, and if this behaviour is intentional then the question is: how can I implement cache redirects to normalise identical objects across queries?
Thanks!
Minimal test case: https://github.com/reubn/apolloiOSBugTestCase
Version
1.9.0
Steps to reproduce the behavior
Minimal test case: https://github.com/reubn/apolloiOSBugTestCase
Logs
No response
Anything else?
No response
The text was updated successfully, but these errors were encountered: