Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
GraphQL Caching
# Define an instrumentation that performs the caching
class CachingInstrumentation
def instrument(_type, field)
return field unless field.metadata.include?(:cache_proc)
old_resolver = field.resolve_proc
new_resolver = -> (obj, args, ctx) do
# Get the caching key
cache_key = field.metadata[:cache_proc].call(obj, args, ctx)
# Attempt to retrieve the value from the cache
value = get_from_cache(cache_key)
return value if value
# On a miss, fallback to the old value + store in cache
value = old_resolver.call(obj, args, ctx)
insert_into_cache(cache_key, value)
value
end
# Return the redefined field with the new resolver
field.redefine do
resolve(new_resolver)
end
end
def get_from_cache(key)
# TODO
end
def insert_into_cache(key, value)
# TODO
end
end
# Set up GraphQL Field so that it accepts a proc that will determine the caching value
GraphQL::Field.accepts_definitions(
cache: GraphQL::Define.assign_metadata_key(:cache_proc)
)
SomeType = GraphQL::ObjectType.define do
name "Something"
field :myField, !types.String do
# Flag a field as cacheable
cache -> (obj, args, ctx) { "Something.myField(#{obj.id})" }
resolve -> (obj, args, ctx) { obj.expensive_computation }
end
end
# Instrument your schema
Schema.define do
# ... other stuff here
instrument(:field, CachingInstrumentation.new)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment