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

Let InMemoryCache return null if cache is empty #5866

Closed
wants to merge 4 commits into from
Closed

Let InMemoryCache return null if cache is empty #5866

wants to merge 4 commits into from

Conversation

jannes-io
Copy link

#1 refers to the feature-request repository:
apollographql/apollo-feature-requests#1

Checklist:

  • If this PR is a new feature, please reference an issue where a consensus about the design was reached (not necessary for small changes)
  • Make sure all of the significant new logic is covered by tests

@apollo-cla
Copy link

@jannes-io: Thank you for submitting a pull request! Before we can merge it, you'll need to sign the Apollo Contributor License Agreement here: https://contribute.apollographql.com/

@jannes-io
Copy link
Author

Failing test because of missing field oversight.
It should only catch the error if the query is not present in cache.

I'll investigate further to come to a nicer solution whilst keeping the missing field errors.

This will allow the missing fields and dangling object errors to continue being thrown while other errors are caught and transformed to null like discussed in #1.
@jannes-io
Copy link
Author

Tests are passing now.

@jannes-io jannes-io requested a review from benjamn January 27, 2020 11:58
@benjamn benjamn changed the title #1 let inMemoryCache return null if cache is empty Let InMemoryCache return null if cache is empty Jan 28, 2020
try {
return this.cache.readQuery<T, TVariables>(options, optimistic);
} catch (e) {
return null;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A blind try-catch block that swallows all exceptions cannot the right way to do this. This repository controls the cache as well as the client, so there's no reason we should need a band-aid like this.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I fully agree, unfortunately I am not familiar enough with the apollo code-base and just wanted to do a suggestion and raise some attention to the implementation of the requested feature as our code-base for a new project is currently suffering from it

// separation is to include c.callback in the cache key for
// maybeBroadcastWatch calls. See issue #5733.
c.callback,
JSON.stringify({ optimistic, rootId, variables }),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please revert these whitespace changes.

@EmreErdogan
Copy link

EmreErdogan commented Feb 6, 2020

Thanks for the PR and thanks for reviewing it. Is this likely to be merged?
@benjamn @jannes-io

@jannes-io
Copy link
Author

@EmreErdogan no, this would indeed solve the issue, but is not a good way to go about it. Someone with more knowledge about the inMemoryCache will have to take a closer look and come up with a solid fix instead of the band-aid that is this PR.

@jannes-io jannes-io closed this Feb 6, 2020
@jannes-io jannes-io deleted the feature/1-inmemorycache-return-null branch February 6, 2020 17:02
benjamn added a commit that referenced this pull request Feb 10, 2020
Writing data to a specific entity object should not require the additional
boilerplate of creating a named fragment with a type condition. All the
cache really cares about is the top-level selection set of the query or
fragment used to read or write data, and from that perspective queries are
an almost perfect substitute for fragments, in almost all cases.

In other words, this code

  cache.writeFragment({
    id,
    fragment: gql`
      fragment UnnecessaryFragmentName on UnnecessaryType {
        firstName
        lastName
      }
    `,
    data: {
      __typename: "UnnecessaryType",
      firstName,
      lastName,
    },
  });

can now be written as just

  cache.writeQuery({
    id,
    query: gql`{ firstName lastName }`,
    data: { firstName, lastName },
  });

Once you get used to using queries instead of fragments, you may begin to
wonder why you ever thought fragments were a good idea. To save you some
existential turmoil: fragments are still a good idea if you really need
their type condition behavior (that is, if you want the fragment to match
only when the `on SomeType` condition holds), but otherwise passing
options.id and options.query to cache.readQuery or cache.writeQuery is a
lot simpler and just as powerful.

If you need further convincing, the cache.readFragment and
cache.writeFragment methods actually convert the given options.fragment
document to a query document (using getFragmentQueryDocument) which
includes the given options.fragment as a ...field. You can skip that
needless conversion by just providing options.query to readQuery or
writeQuery, and reserving readFragment and writeFragment for the rare
cases where fragments actually have advantages over queries.

We are not removing the cache.readFragment and cache.writeFragment methods
at this time, though we may consider deprecating them in the future.

As a side benefit, these changes happen to solve our longest outstanding
feature request, apollographql/apollo-feature-requests#1,
which recently inspired #5866.
That's because options.rootId is now always defined when we do this check:
https://github.com/apollographql/apollo-client/blob/9cd5e8f7552db65437b5e59b605268a336977e45/src/cache/inmemory/inMemoryCache.ts#L130-L134
benjamn added a commit that referenced this pull request Feb 11, 2020
Writing data to a specific entity object should not require the additional
boilerplate of creating a named fragment with a type condition. All the
cache really cares about is the top-level selection set of the query or
fragment used to read or write data, and from that perspective queries are
an almost perfect substitute for fragments, in almost all cases.

In other words, this code

  cache.writeFragment({
    id,
    fragment: gql`
      fragment UnnecessaryFragmentName on UnnecessaryType {
        firstName
        lastName
      }
    `,
    data: {
      __typename: "UnnecessaryType",
      firstName,
      lastName,
    },
  });

can now be written as just

  cache.writeQuery({
    id,
    query: gql`{ firstName lastName }`,
    data: { firstName, lastName },
  });

Once you get used to using queries instead of fragments, you may begin to
wonder why you ever thought fragments were a good idea. To save you some
existential turmoil: fragments are still a good idea if you really need
their type condition behavior (that is, if you want the fragment to match
only when the `on SomeType` condition holds), but otherwise passing
options.id and options.query to cache.readQuery or cache.writeQuery is a
lot simpler and just as powerful.

If you need further convincing, the cache.readFragment and
cache.writeFragment methods actually convert the given options.fragment
document to a query document (using getFragmentQueryDocument) which
includes the given options.fragment as a ...field. You can skip that
needless conversion by just providing options.query to readQuery or
writeQuery, and reserving readFragment and writeFragment for the rare
cases where fragments actually have advantages over queries.

We are not removing the cache.readFragment and cache.writeFragment methods
at this time, though we may consider deprecating them in the future.

As a side benefit, these changes happen to solve our longest outstanding
feature request, apollographql/apollo-feature-requests#1,
which recently inspired #5866.
That's because options.rootId is now always defined when we do this check:
https://github.com/apollographql/apollo-client/blob/9cd5e8f7552db65437b5e59b605268a336977e45/src/cache/inmemory/inMemoryCache.ts#L130-L134
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Feb 16, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants