Skip to content

Caching and invalidation mechanisms (plugins, directives) of Apollo GraphQL

License

Notifications You must be signed in to change notification settings

haroldwaste/apollo-response-cache

 
 

Repository files navigation

apollo-response-cache

Publish Status Test Status Commitizen friendly

Caching and invalidation mechanisms (plugins, directives) of Apollo GraphQL, used by matters-server.

responseCachePlugin is forked from apollo-server-plugin-response-cache.

How it works?

Cache Mechanisms

On each query request,

  1. responseCachePlugin creates an empty key set, and injects it to the context.
  2. @logCache collects nodes on its field, then add to the key set.
  3. responseCachePlugin writes query response cache (fqc) and node-fqc key mapping to in-memory data store.

Once a mutation updates this node, @purgeCache will purge related fqc.

Usage

Install package:

npm i @matters/apollo-response-cache

Add plugin and directives to the constructor:

import {
  responseCachePlugin,
  LogCacheDirective,
  PurgeCacheDirective,
} from '@matters/apollo-response-cache'

const server = new ApolloServer({
  plugins: [responseCachePlugin()],
})

const schema = makeExecutableSchema({
  schemaDirectives: {
    logCache: LogCacheDirective(),
    purgeCache: PurgeCacheDirective(),
  },
})

Add definitions to your schema:

directive @logCache(
  type: String!
  identifier: String = "id"
) on FIELD_DEFINITION

directive @purgeCache(
  type: String!
  identifier: String = "id"
) on FIELD_DEFINITION

Use in the schema:

type Query {
  article(id: ID!): Article! @logCache(type: "Article")
}

type Mutation {
  archiveArticle(id: ID!): Article! @purgeCache(type: "Article")
}

You can also purge cache in the resolver:

const schema = makeExecutableSchema({
  schemaDirectives: {
    purgeCache: PurgeCacheDirective({ extraNodesPath: '__invalid_nodes__' }),
  },
})

const resolvers = {
  Mutation: {
    archiveArticle: (parent, args, context) => {
      // ...
      article.__invalid_nodes__ = [
        {
          id: '2',
          type: 'Article',
        },
        {
          id: '3',
          type: 'Comment',
        },
      ]

      return article
    },
  },
}

Customize node type & id resolvers

You might want a custom function to resolve node's type and id since it may be a union or interface type.

const typeResolver = (type: string, result: any) => {
  if (['Node', 'Response'].indexOf(type) >= 0) {
    return result.__type
  }
  return type
}
const idResolver = (type: string, result: any) => {
  if (['Node', 'Response'].indexOf(type) >= 0) {
    return result.__unusual_id__
  }
  return result.id
}

const schema = makeExecutableSchema({
  schemaDirectives: {
    purgeCache: PurgeCacheDirective({ typeResolver, idResolver }),
  },
})

TODOs

  • responseCachePlugin
  • @logCache
  • @purgeCache
  • Unit Test

About

Caching and invalidation mechanisms (plugins, directives) of Apollo GraphQL

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • TypeScript 96.3%
  • JavaScript 3.0%
  • Shell 0.7%