Skip to content
This repository has been archived by the owner on Dec 19, 2019. It is now read-only.

[Prototype] Server-side query caching #17

Closed
paliarush opened this issue May 16, 2018 · 3 comments
Closed

[Prototype] Server-side query caching #17

paliarush opened this issue May 16, 2018 · 3 comments
Assignees
Labels
framework magento-core Epics and issues assigned to Magento core team members. medium

Comments

@paliarush
Copy link
Contributor

paliarush commented May 16, 2018

Varnish:

  1. Start accepting GraphQL queries as GET requests
    • see proposal from @paales in comments
    • example, http://magento.api/graphql?query={queryName{fieldName}}. The whole query goes to the URL
    • enables caching with Varnish without new dependencies
    • caching will not work with GraphQL queries sent as POST requests
    • requires slight modification of existing Magento GraphQL framework to start accepting GET requests
    • recommended by https://graphql.org/learn/serving-over-http

Use cases that should be supported

  1. Products query contains a list of category assignments. In this case when the category is changed the product cache must be invalidated. If products query didn't contain category assignment, then changes in the category must not affect the product cache.
  2. Queries, which contain search criteria may get outdated when the new products are added or any product in the system is modified. Cache should be invalidated in this case.

Prototype

https://github.com/magento/graphql-ce/tree/GraphQL-Cache-Prototype
Has the following concepts tested:

  • GraphQL queries via HTTP GET
  • Generation of Varnish tags in a modular way without direct modifications of the resolvers
  • Caching of product queries and invalidation on related product updates

Considered alternatives

  1. Implement Varnish support for POST requests
@paliarush paliarush added framework for-grooming This issue needs to be discussed before it can be worked on labels May 16, 2018
@paales
Copy link
Contributor

paales commented May 29, 2018

Top level specifications to implement caching for GraphQL with Varnish.

Use Magento’s existing caching strategies an extend them to let them also work for the GraphQL requests.

GraphQL moves all its logic to the content of the response and moves away from the HTTP nature of the request, this can introduce compatibility issues with other transport protocols: GraphQL subscriptions over web sockets for example. Although, it can be argued that implementing a HTTP-only caching layer is good-enough.

The easiest way to implement a caching layer is to handle the /graphql query requests as a normal GET requests (and handle the mutation requests as a POST):
- Add the X-Magento-Tags header to responses like a normal HTTP GET request would.
- Add the X-Magento-Vary header to the response like a normal HTTP GET request would.
- Add the Cache-control = private header to the response if the response is uncacheable.
- define it’s tags (vary header can be automatic). If no tags are defined, the query will throw an exception, it is required to be explicit about the cache tags.
- Add a Varnish handler to also handle /graphql query requests.
- mutations will never be cached by the server (but can be cached by a client library).
- Let the current cache-flush system also flush all the GraphQL requests.

The advantage of this strategy is that it is relatively straightforward to implement with Varnish (as the complete request is cached), while still being more fine-grained than caching a complete page (multiple queries will probably be executed per page load).

With this setup we do not introduce any new dependencies. We use existing libraries/systems (every should should use varnish anyway). This means that there is almost zero overhead for new developers to implement proper caching. If the cache tag flush works properly there should never be any stale data.

You are unable to use a library like https://www.apollographql.com/docs/link/links/batch-http.html. With such a library a lot of cache misses could disappear, as it is highly likely that private queries are sent with public ones. The argument could be made that this library is deprecated because of the face of http/2.

A more specialized solution would be a GraphQL-aware caching layer, which is comparable to Apollo Engine which can for example cache the public parts of a query. This is probably more complex to implement and might be a nice V2 version of the caching layer.

@misha-kotov
Copy link

Thanks Paul for your thoughts on this topic! I'll have our technical folks take a look at your suggestions.

@paales
Copy link
Contributor

paales commented May 29, 2018

@paliarush I didn't explicitly meant that we should switch to GET requests directly, but it seems that is easily possible as well by providing a custom fetch method to the apollo-link-http library:
apollographql/apollo-link#236 (comment)

Might be easier then if Varnish requires additional libraries to get everything up-and-running.

@paliarush paliarush self-assigned this Sep 18, 2018
@paliarush paliarush removed the for-grooming This issue needs to be discussed before it can be worked on label Oct 29, 2018
@paliarush paliarush changed the title Query Caching Server-side query caching Oct 29, 2018
@paliarush paliarush changed the title Server-side query caching [Prototype] Server-side query caching Oct 29, 2018
@paliarush paliarush added medium and removed large labels Oct 29, 2018
@cherdman cherdman added the magento-core Epics and issues assigned to Magento core team members. label Apr 10, 2019
magento-engcom-team pushed a commit that referenced this issue Jul 5, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
framework magento-core Epics and issues assigned to Magento core team members. medium
Projects
None yet
Development

No branches or pull requests

4 participants