Не удается заставить кэш redis работать с apollo server express

#node.js #express #redis #apollo-server

Вопрос:

Я пытаюсь настроить систему кэширования для своего сервера apollo Express, но, похоже, руководства, которым я следовал, взяты из официальных документов: https://www.apollographql.com/docs/apollo-server/performance/caching/#memcachedredis-setup не делайте вид, что работаете на меня.

Я могу убедиться, что в моем распознавателе запроса, который продолжает попадать в журнал консоли, он попадает каждый раз, а не только один раз, а затем устанавливается кэш

 // 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;
};
 

Вот мой код:
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;

 

Я также проверяю, чтобы мое веб-приложение Cache-Control: max-age=300 также отправляло заголовок в запросе graphql. Я также проверил свой сервер Redis и убедился, что после выполнения запроса graphql новые ключи не добавляются.

Я также попытался установить директиву CacheControl для типа, подобного:

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

но и с этим не повезло. Я ценю любую помощь, спасибо!

Комментарии:

1. Есть какие-нибудь успехи с этим вообще? Мой тоже не работает — на моем сервере redis нет записей

2. @alexr89 к сожалению, нет

Ответ №1:

Используете ли вы koa или express, вам нужно будет добавить эти плагины: 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').defau<
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,
    }),
  ],
});
 

Важные примечания:

  • Измените этот код context.ctx.header ? context.ctx.header.authorization , чтобы получить идентификатор сеанса для конкретного пользователя.
  • Убедитесь, что apollo-server-express используемая вами версия запускает события willResolveField для получения значений из кэша и willSendResponse для установки значения в кэше, когда это необходимо (потому что у меня была проблема с версией v2.25.x в Koa).
  • Использование const redis = require('redis'); не будет корректно устанавливать ttl (maxAge). Поэтому, пожалуйста, убедитесь ioredis , что вместо этого вы можете установить ttl.