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

Is there any documentation on how CacheKeyResolver works for normalized cache #1370

Closed
anup1245 opened this issue Jun 16, 2019 · 7 comments
Closed

Comments

@anup1245
Copy link

Wanted to know how CacheKeyResolver works for normalized cache.
what is the difference between fromFieldRecordSet and fromFieldArguments, and when are they called?

@davidliu
Copy link

davidliu commented Aug 2, 2020

Ugh, this issue really needs to be resolved. Took me quite a while to figure out this out. Until this gets better documentation, hopefully my comment can help others out (and maybe someone can also correct me if I got this wrong).

fromFieldRecordSet: This is used for saving an object to the cache. When you retrieve an object from the network, the cache will call this method to know what the proper key is for saving. This is called for each object nested, not just the top level.

fromFieldArguments: This is used for loading an object from the cache. When you request an object, the cache will call this method to see what key to look for in the cache. This is called for each object nested in the requested response, not just the top level.

For example, going off of the example given in the normalized cache documentation:

query BookWithAuthorName {
  favoriteBook {
    id
    title
    author {
      id
      name
    }
  }
}

query AuthorById($id: String!) {
  author(id: $id) {
      id
      name
    }
  }
}

Calling the BookWithAuthorName query will result in:

  1. fromFieldArguments for favoriteBook
  2. fromFieldArguments for favoriteBook.author
  3. (After network retrieval) fromRecordSet for favoriteBook with the object info.
  4. (After network retrieval) fromRecordSet for favoriteBook.author with the object info.

Calling AuthorById afterwards will result in:

  1. fromFieldArguments for author(id)

If configured properly, the fromFieldArguments will generate the same cache key as the previous favoriteBook.author cache key, and the cache can hit properly.

@martinbonnin
Copy link
Contributor

For anyone who comes here, there's now a dedicated page for the normalized cache. You can also follow #2331 for updates about normalized cache improvements.

@pkoutsovasilis
Copy link

Hello, I just started messing with the normalized cache so sorry if my question to follow is already answered or the answer is obvious but I fail to see it.

With the current way CacheKeyResolver works it is sound and clear to me how the cache, in the above example, is able find the author (if any) of the AuthorById query when a BookWithAuthorName query has previously succeeded, at least once. However, it is not clear to me how I can get the book when I have the author (going up the leaf?!). Any clearance/hints on that would be highly appreciated. thx

@davidliu
Copy link

davidliu commented Aug 26, 2020

From the given example, it'd be impossible, as the AuthorById query doesn't return any book information, so there'd be no book information to retrieve from the cache, even if the keys were somehow resolved correctly. Therefore, the question is moot.

@pkoutsovasilis
Copy link

From the given example, it'd be impossible, as the AuthorById query doesn't return any book information, so there'd be no book information to retrieve from the cache, even if the keys were somehow resolved correctly. Therefore, the question is moot.

Yeah I was referring more on the how the CacheKeyResolver could be employed to provide such capability in general, not this particular example. The only possible way, I see this happening, is actually providing some fields inside the Author that can be used to calculate the book id?! but this seems like a really hacky way to go.

@davidliu
Copy link

davidliu commented Aug 26, 2020

A more reasonable example would be if the Author schema included a books field, which had a list of books the author had written. Then, just like how you can cache an author from a top level book query (since a book contains information on its author), you could cache each book in an author.

query AuthorById($id: String!) {
  author(id: $id) {
      id
      name
      books {
        id
      }
    }
  }
}

Since ids are globally unique in the example, all you'd need to do is fetch the id for each book and associate it with its entry.

The page on cache normalization already shows an example of how to do it with books -> author, and it would also work in the reverse case.

The only possible way, I see this happening, is actually providing some fields inside the Author that can be used to calculate the book id?! but this seems like a really hacky way to go.

I'm not sure if this is really hacky at all. It feels like GraphQL encourages this, as you can easily refer to another object type from within an object, and it'd be very reasonable to be able to look up all the Book objects written by an Author. I'd take a look at this fake schema, which does something similar, where a User type has the capability to look up that User's posts.

@martinbonnin
Copy link
Contributor

Hi everyone 👋

Apollo Android 3 introduces declarative cache directives that make it easier to define your cache keys without implementing a CacheKeyResolver.

If you still required the flexibility of programmatic cache ids, there's also a separate page for that. Hope this helps!

I'm going to close this issue as it's more than one year old. If anything's unclear, please feel free to open a new issue and we'll dive into it

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants