Skip to content
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

Feature request: updateQuery method that can operate on all variables a query has been cached with #230

Open
jedwards1211 opened this issue May 22, 2020 · 13 comments
Labels
📕 cache Feature requests related to the cache project-apollo-client (legacy) LEGACY TAG DO NOT USE

Comments

@jedwards1211
Copy link

@benjamn

With the removal of cache.modify, there's still no simple way to remove a deleted item from all cached queries, since they could be called with many different variables. (apollographql/apollo-client#6289 (comment), apollographql/apollo-client#6289 (comment)).

To solve this without the problems cache.modify had, I propose an updateQuery method, as illustrated below. This would be so similar to the existing readQuery/writeQuery methods that it wouldn't risk confusing user in the way that cache.modify did, and it would be very easy to document. But unlike readQuery and writeQuery, it would allow us to update query results for all cached variables in one fell swoop by omitting the variables option.

It would also be more convenient for most existing cases where readQuery followed by writeQuery is used (I've been using a userland updateQuery method for awhile, albeit without the all-cached-variables capability).

type Entry {
  id: String!
}

type Query {
  entries (search: String!): [Entry!]!
}

type Mutation {
  removeEntry (id: String!): String!
}

const query = gql`
  query ($search: String!) {
    entries(search: $search) {
      id
    }
  }
`

async function removeEntry(variables: RemoveEntryVariables, client: ApolloClient<NormalizedCacheObject>): Promise<void> {
  await client.mutate<RemoveEntry, RemoveEntryVariables>({
    mutation: removeEntryMutation,
    variables,
    optimisticResponse: {
      removeEntry: variables.id
    },
    update(cache, {data: {removeEntry}}) {
      cache.updateQuery({
        query,
        // variables: would be optional, if omitted updater is called with all cached query variables and corresponding data
        updater: ({data, variables}: {data: QueryData, variables: QueryVariables}): QueryData => ({
          ...data,
          entries: data.entries.filter(e => e.id !== removeEntry.id),
        })
      });
      cache.gc();
    }
  })
}
@danReynolds
Copy link

One problem with this structure is just that the cache doesn't store variables for queries. It could support iteration like this but it'd have to pass you the unique storeFieldName instead of the variables.

@jedwards1211
Copy link
Author

jedwards1211 commented May 22, 2020

@danReynolds I mean it sort of does already, because the variables are serialized in the cache keys. But yeah ideally they should be stored unserialized somewhere, as well as efficient data structures that can point us to all the variable bindings and corresponding data for a given query or field.

Choice of implementation details (like store field names) should support the goals of an ideal API design, not the other way around. Even if something is not possible with the current implementation, let's keep open minds about what can be made possible.

I'm sure the Apollo team will make these improvements to the cache sooner or later because it's going to be the only way to manage cache updates in a large app in a sane way unless you force the responsibility for storing variables into userland. Right now refetching is virtually the only option in a lot of cases.

For example, if you want to insert a newly created item in the correct sorted position in all applicable lists in the cache, you probably need to know variables that determine the sort order and list range for each of those queries.

@danReynolds
Copy link

danReynolds commented May 23, 2020

Yea you can't just parse the store field name though because field directives for example are also added to it. I'd vastly prefer for them to store variables separately as a first class entity of fields that we can access. I assume the concern with that is mostly bloating the cache size.

@jedwards1211
Copy link
Author

It's hard to imagine a case where the variables take up even close to as much space as the data though

@lukeramsden

This comment has been minimized.

@darkbasic
Copy link

It's hard to imagine a case where the variables take up even close to as much space as the data though

Imagine having a search field in your query: variables size can easily get huge.

@jedwards1211
Copy link
Author

@darkbasic you're saying if the search is really long? Or that each keystroke would create another set of variables? (I'm assuming they wouldn't remain cached forever unless data gets loaded, which would probably be larger than the search term)

@darkbasic
Copy link

darkbasic commented May 25, 2020

Not each keystroke because you definitely want to debounce this, but you will end up with plenty of search terms anyway. Lots of them could have little to no results.

@jedwards1211
Copy link
Author

jedwards1211 commented May 25, 2020

Only one will be active though so others would get garbage collected if the cache gets too big right?

@jedwards1211
Copy link
Author

jedwards1211 commented May 25, 2020

Also since the variables already get stringified into the cache keys, any size problems are already present. Storing the unstringified variables wouldn't be a very substantial increase relative to that.

@jedwards1211
Copy link
Author

@benjamn although you're restoring cache.modify, I think it will still be hard to perform some kinds of updates without a feature like this, especially inserting a newly created item into all the sorted lists where it belongs. (In my project the sort order and page range are determined by variables.)

@hwillson
Copy link
Member

Thanks for the great discussion here @jedwards1211. We'd like to keep issues here for bugs only, so I'm going to transfer this issue over to our FR repo. Thanks again!

@hwillson hwillson transferred this issue from apollographql/apollo-client May 27, 2020
@jedwards1211
Copy link
Author

I think I probably failed to notice the link in the feature request template, my apologies!

@jpvajda jpvajda added the project-apollo-client (legacy) LEGACY TAG DO NOT USE label Aug 24, 2022
@jerelmiller jerelmiller added the 📕 cache Feature requests related to the cache label Apr 6, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
📕 cache Feature requests related to the cache project-apollo-client (legacy) LEGACY TAG DO NOT USE
Projects
None yet
Development

No branches or pull requests

7 participants