Caching and invalidation mechanisms (plugins, directives) of Apollo GraphQL, used by matters-server
.
responseCachePlugin
is forked from apollo-server-plugin-response-cache
.
On each query request,
responseCachePlugin
creates an empty key set, and injects it to the context.@logCache
collects nodes on its field, then add to the key set.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
.
Note: there are breaking changes in API from 1.4.0 to 2.0.0, see below Breaking changes section for more info
Install package:
npm i @matters/apollo-response-cache
Add plugin and directives to the constructor:
import {
logCacheDirective,
purgeCacheDirective,
responseCachePlugin,
} from '@matters/apollo-response-cache'
const {typeDef: logCacheDirectiveTypeDef, transformer: logCacheDirectiveTransformer} = logCacheDirective()
const {typeDef: purgeCacheDirectiveTypeDef, transformer: purgeCacheDirectiveTransformer} = purgeCacheDirective()
let schema = makeExecutableSchema({
typeDefs: [yourTypeDef, logCacheDirectiveTypeDef, purgeCacheDirectiveTypeDef]
})
schema = logCacheDirectiveTransformer(
purgeCacheDirectiveTransformer(schema)
)
const server = new ApolloServer({
schema,
plugins: [responseCachePlugin()],
})
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
},
},
}
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 }),
},
})
- Support apollo-server v4 now, but drop support for apollo-server v3 and graphql-tools v8 and below
- All APIs, including plugin option, directives, helpers interface, changed:
a. pulgin constructor take redis client (type
Redis
from ioredis) instead ofRedisCache
from deprecated apollo-server-cache-redis b. invalidateFQC take redis instead ofRedisCache
c. directives api is totally changed to function way, as graphql-tools/utils v8 depreacated class base SchemaDirectiveVisitor
If hit Types have separate declarations of a private property '__identity'
when build apollo server codebase, make sure both direct dependency on @apollo/server
and this package dependency on @apollo/server
share totally same version.
- responseCachePlugin
- @logCache
- @purgeCache
- Unit Test