Write a cache layer for each resolver in GraphQL Shield style with Memcached
- Memcached
- GraphQL Middleware
- Your GraphQL Schema
$ yarn add graphql-cached
import { cached } from 'graphql-cached'
import { applyMiddleware } from 'graphql-middleware'
import Memcached from 'memcached'
import schema from './schema'
const memcached = new Memcached('my.memcached.host:11211')
// Generated resolver types by `@graphql-codegen/cli`
import { Resolvers } from './__generated__/resolvers'
import { Context } from './context'
const middleware = cached<Context, Resolvers>(
{
User: {
image: {
key(parent, args, context) {
// it's type-safe!
return parent.imageId
},
lifetime: 5,
serializer: {
serialize(item) {
return item
},
deserialize(serializedItem) {
return new Image(serializedItem)
},
},
},
},
},
{
memcached,
contextKey(context) {
return 'v1.' + context.user?.role || 'Anonymous'
},
}
)
// Now schema is automatically cached!
const cachedSchema = applyMiddleware(schema, middleware)
key
:fieldKey
generation function
lifetime
: How much time to keep the cache (seconds) (default: 10 seconds)serializer
: Preprocess item before storing in cache and after fetching from cache
memcached
: Memcached client instancecontextKey
: Key generation function based onContext
beforeGet
: Triggered before cache fetchingafterGet
: Triggered after cache fetchingbeforeSave
: Triggered before cache storingafterSave
: Triggered before cache storingonHit
: Triggered when cache hitonMiss
: Triggered when cache miss
{contextKey}${typeName}${fieldName}${fieldKey}
v1.Admin$User$image$dbf66e27-9bb4-5682-b890-ecf34fe63333
v1.User$Query$user${"where":{"id":"57c5fb3f-a5e7-5b4f-a7ed-ab50281b8222"}}
If there are resolvers with different responses for different users, carefully write the key generation function. Items cached for one user may be visible to other users.
Also, if there is a cached item, the existing resolver does not work. If you want to do permission-related logic before cache layer, I recommend using it with graphql-shield.
const schemaWithMiddleware = applyMiddleware( schema, authMiddleware, // created with graphql-shield cachedMiddleware // created with graphql-cached )For more information on how GraphQL Middleware works, check out GraphQL Middleware.
If you have a feature request or a bug, please create a new issue. And also, pull requests are always welcome🙏