Apollo cache is getting reset back to old data

683 Views Asked by At

I'm building an Expo mobile app using AWS AppSync and Apollo and I've got an intermittent but very serious issue with the cache getting corrupted, or at least not being updated properly. Unfortunately, because I'm using AppSync and I want the offline capability, I can't upgrade to the latest Apollo client, so as a result the data is stored in Redux, there are 4 top-level keys: offline, rehydrated, appsync and appsync-metadata.

This is what I expect to happen:

  1. GraphQL query for a "project" returns the correct data
  2. This data is written into the cache. In particular, I'm expecting that in appsync.ROOT_QUERY there'll be an entry for the project, something like getProject({"input":{"id":"project-7"}}) plus a top level entry in appsync for the project with all of its properties.
  3. When I do execute a mutation, I'm expecting the project entry to be updated.
  4. Since the project is updated, I'm expecting the UI to be refreshed reflecting the updated data.

Most of the time, this happens exactly as above. However, sometimes something happens to the cache. I'm not sure exactly what, but it gets into a weird state and I can't fix it.

Here are the symptoms:

  1. When I start the app, the cache is initialised to an "old" state, one that doesn't include the query for project-7 even though I had queried for it just moments before killing the app.
  2. When I do a search for project-7, it then adds the getProject...project-7 query to the cache and an entry for project-7, but for some reason doesn't seem to have all the fields.
  3. When I do a mutation, there's an AAS_WRITE_CACHE which actually removes the getProject...project-7 entry from the query cache! The mutation succeeds though, I can see that the data in the AppSync server is updated, and the client doesn't log any errors anywhere.
  4. The UI does NOT update.

I tried adding an update to the mutation so that I could update the cache myself, but when I execute const data = proxy.readQuery({ query: ProjectQuery } ... ) (specifying project-7), it throws an exception to say that it can't find that query, so I can't update the project. If I manually re-get the project, then everything works again until the next mutation.

What's really difficult, is that once my app is in this state, I can't work out how to fix it. I've tried client.resetStore() but it just gets rehydrated. I've tried calling AsyncStorage.clear() and then stopping the app and restarting it, but that doesn't work either. How can this be? Where is it storing the data?

It's worth saying again that on most of the devices I've tested it on (both Android and iOS), it works for days without any problems, but on one Android device in particular, it happens once every day or two. Twice I've been able to fix it using the "Clear Async storage" in the React Native Debugger, but now even that doesn't seem to fix it.

So, here are my questions:

  1. Can anyone suggest what might be causing the cache to get into this weird state? Or how I can try and track down the problem.
  2. Where is it storing the data that it then puts back? There are snapshots of the cache in appsync-metadata but surely they should also be removed when I clear all the AsyncStorage?

I'm really stuck!!

PS Here are the relevant (I think) packages I'm using:

    "apollo-client": "^2.5.1",
    "aws-amplify": "^1.1.27",
    "aws-amplify-react-native": "^2.1.11",
    "aws-appsync": "^1.7.2",
    "aws-appsync-react": "^1.2.7",
    "expo": "^33.0.0",
    "graphql": "^14.3.0",
    "graphql-tag": "^2.10.1",
    "react": "16.8.3",
    "react-apollo": "^2.5.8",
0

There are 0 best solutions below