'Can't get redis cache to work with apollo server express

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!



Solution 1:[1]

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.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Ehab Terra