0

I'm trying to setup a caching system for my apollo express server, but it seems like the guides I've followed from the official docs: https://www.apollographql.com/docs/apollo-server/performance/caching/#memcachedredis-setup do not appear to work for me.

I can verify that in my resolver for a query that it keeps getting hit by console logging that it is being hit each time instead of only being hit once and then the cache being set

// my resolver definition
const getUserProfile = async (_, args, context, info) => {
  info.cacheControl.setCacheHint({ maxAge: 300 });
  console.log('MISS, set cache hint') // this console logs every time instead of just once
  return context;
};

Here is my code: server.js

...
const redisClient = require('./cacheClient');

  let httpServer;
  if (process.env.ENV === 'prod') {
    httpServer = httpCreateServer(app);
  } else {
    httpServer = httpsCreateServer(
      {
        key: fs.readFileSync('./localhost-key.pem'),
        cert: fs.readFileSync('./localhost.pem'),
      },
      app
    );
  }

  const apolloServer = new ApolloServer({
    typeDefs,
    resolvers,
    cache: new BaseRedisCache({
      client: redisClient
    }),
    cacheControl: true,
  });

  apolloServer.context = ({ req }) => ({
    ...
  });

  await apolloServer.start();

  apolloServer.applyMiddleware({ app });

  httpServer.listen(PORT, () =>
    console.log(`Server is now running on port ${PORT}`)
  );

cacheClient.js

require('dotenv').config();

const { REDIS_SERVER, REDIS_PORT } = process.env;

const redis = require('redis');

const client = redis.createClient({
  host: REDIS_SERVER,
  port: REDIS_PORT,
});

client.on('connect', () => {
  console.log('Redis client connected');
});

client.on('message', (channel, message) => {
  console.log(`Received ${message} from ${channel}`);
});

module.exports = client;

I'm also making sure my web app is sending a Cache-Control: max-age=300 header on the graphql query as well. I also checked my Redis server and verified that no new keys are added after making the graphql query.

I have also tried setting the cacheControl directive onto the type like:

type UserProfile @cacheControl(maxAge: 300) {
  ...
}

but no luck with that either. I appreciate any help, thank you!

Dom Stepek
  • 291
  • 2
  • 11

1 Answers1

0

Whether you use koa or express, you will need to add these plugins: https://www.apollographql.com/docs/apollo-server/api/plugin/cache-control/ https://www.apollographql.com/docs/apollo-server/performance/caching#identifying-users-for-private-responses

...
const responseCachePlugin = require('apollo-server-plugin-response-cache').default;
const { ApolloServerPluginCacheControl } = require("apollo-server-core");

const server = new ApolloServer({
  typeDefs,
  resolvers,
  plugins: [responseCachePlugin({
      sessionId: ({ context }) => (context.ctx.header ? context.ctx.header.authorization : null),
    }),
    ApolloServerPluginCacheControl({
      // Cache everything for 1000 seconds.
      defaultMaxAge: 1000,
      // Don't send the `cache-control` response header.
      calculateHttpHeaders: false,
    }),
  ],
});

Important Notes:

  • Change this code context.ctx.header ? context.ctx.header.authorization to get session Id for specific user.
  • Make sure that the version of apollo-server-express you use will fire events willResolveField for getting values from the cache and willSendResponse for setting the value in cache when needed (because I had a problem with v2.25.x in Koa).
  • Using const redis = require('redis'); will not set ttl (maxAge) correctly. So, please make sure to use ioredis instead to be able to set ttl.