Reputation: 1025
I am trying to setup a cache according to this guide for one expensive query that has a result that changes only once a day. The query takes 7-8 seconds and most it is after the DB query, because the response returned from the resolver must be heavily processed.
I am using apollo-server-express
library and the change pluging is apollo-server-plugin-response-cache
.
This is what I have done:
server.js
const { ApolloServer } = require('apollo-server-express')
const responseCachePlugin = require('apollo-server-plugin-response-cache')
const server = new ApolloServer({
typeDefs,
resolvers,
context: async ({ req }) => {
// ...
},
plugins: [responseCachePlugin()]
resolvers.js
personDetails: async (root, args, ctx, info) => {
info.cacheControl.setCacheHint({ maxAge: 600 })
const persons = await Person.find({}).populate('details')
// processing the data
return processedData
}
I expect the resolver to run once and then after that the response should be returned from the cache almost instantly. This doesn't work. I am doing something wrong or I haven't understood how this should work.
I tried to put cache hints also in the schema, but didn't get any better results.
Upvotes: 4
Views: 3600
Reputation: 31
I understand that this is an old question but it might help someone solve server side caching issue in Apollo.
So as per my understanding the apollo-server-plugin-response-cache
plugin only works if the response from the underlying REST API have control-cache header. In case there is no cache-control header in your REST API it can be overriden in restDataSouce GET calls as below.
return this.get(`uri_path`,"", {cacheOptions: { ttl: 1}});
After that continue using info.cacheControl at the resolvers as suggested in the example from the question snippets. maxAge there will override the time mentioned in the cacheOptions.
Upvotes: 1
Reputation: 102247
It should work. Here is a working example:
server.ts
:
import { ApolloServer, gql } from 'apollo-server-express';
import express from 'express';
import responseCachePlugin from 'apollo-server-plugin-response-cache';
const typeDefs = gql`
type Query {
personDetails: String
}
`;
const resolvers = {
Query: {
personDetails: async (root, args, ctx, info) => {
console.log(`[${new Date().toLocaleTimeString()}] Query.personDetails`);
info.cacheControl.setCacheHint({ maxAge: 10 });
return 'This is person details';
},
},
};
const app = express();
const apolloServer = new ApolloServer({
typeDefs,
resolvers,
plugins: [responseCachePlugin()],
});
apolloServer.applyMiddleware({ app });
const server = app.listen({ port: 4000 }, () => {
console.log(`The server is running in http://localhost:4000${apolloServer.graphqlPath}`);
});
The request logs:
The server is running in http://localhost:4000/graphql
[1:51:27 PM] Query.personDetails
[1:51:52 PM] Query.personDetails
The response header:
cache-control: max-age=10, public
The first graphql request send at [1:51:27 PM]
. In the next 10 seconds, all requests sent will hit the cache(defaults to an in-memory LRU cache), which means the graphql resolver personDetails
will not execute. The graphql response will be read from the cache and sent to client-side.
After 10 seconds, I send another graphql request at [1:51:52 PM]
. The cache is expired. So this request will not hit the in-memory cache. The graphql resolver will execute and generate a new value.
source code: https://github.com/mrdulin/apollo-graphql-tutorial/tree/master/src/stackoverflow/57243105
Upvotes: 3