At StackShare, we’ve been experimenting with GraphQL for some of our new features. We’re using Apollo on the front end and GraphQL Ruby on the back end. Don’t worry, we’ll be publishing a full retrospective on why we chose GraphQL and how it is implemented soon.
We’ve encountered a couple of gaps in the Ruby GraphQL implementation. One of the biggest pieces missing from the gem is a clean means of implementing caching of resolved fields. GraphQL queries can get complicated - so much so that we have concepts like “max complexity” in our schema.
Of course you can implement it easy enough:
< 1.8
field :my_field, types.Int do
resolve ->(obj, args, ctx) {
Rails.cache.fetch([obj.id, 'my_field']) do
# ... some long running calculation
end
}
end
> 1.8
field :my_field, Int
def my_field
Rails.cache.fetch([obj.id, 'my_field']) do
# ... some long running calculation
end
end
But now we have to write a cache block and key in each resolver to be cached. This is a maintenance nightmare in terms of cache keys and is just plain ugly Ruby.
To combat these issues, we implemented a custom middleware for graphql-ruby that handles key construction and cache reads/writes transparently. Now when we want to cache a field, all we have to do is add a keyword parameter to the field:
field :my_field, Int, cache: true
The value is cached under a key that uniquely identifies this field for this object. After working with it for a while, we’ve decided to open-source our solution as graphql-cache. The gem is currently in pre-production release and only supports version 1.8.0
of the graphql-ruby gem, but we plan to add support for previous versions of both it and Rails.
Enjoy!