Apollo Server - путаница с параметрами кэша / источника данных

Документы ( https://www.apollographql.com/docs/apollo-server/features/data-sources.html) показывают такой код:

const { RedisCache } = require('apollo-server-cache-redis');

const server = new ApolloServer({
  typeDefs,
  resolvers,
  cache: new RedisCache({
    host: 'redis-server',
    // Options are passed through to the Redis client
  }),
  dataSources: () => ({
    moviesAPI: new MoviesAPI(),
  }),
});

Мне было интересно, как это cache ключ используется, учитывая, что кажется, что кеширование на самом деле реализовано в нечто вроде MoviesAPI() а затем используется через context.dataSources.moviesAPI.someFunc(), Например, скажем, я хотел реализовать свой собственный кеш для базы данных SQL. Это было бы похоже

  cache: new RedisCache({
    host: 'redis-server',
  }),
  dataSources: () => ({
    SQL: new SQLCache(),
  }),
});

где SQLCache имеет свою собственную функцию, которая подключается к RedisCache лайк:

  getCached(id, query, ttl) {
    const cacheKey = `sqlcache:${id}`;

    return redisCache.get(cacheKey).then(entry => {
      if (entry) {
        console.log('CACHE HIT!');
        return Promise.resolve(JSON.parse(entry));
      }
      console.log('CACHE MISS!');
      return query.then(rows => {
        if (rows) redisCache.set(cacheKey, JSON.stringify(rows), ttl);
        return Promise.resolve(rows);
      });
    });
  }

Так что это значит, у меня есть RedisCache в обоих ApolloServercache ключ и dataSource реализация. Очевидно, что RedisCache используется в dataSource реализация, но тогда что это ApolloServercache ключ точно?

Также на клиенте примеры в основном показывают использование InMemoryCache вместо кеша Redis. Должен ли кеш клиента Apollo отличаться от кеша сервера или такой же кеш, как RedisCache быть в обоих местах?

1 ответ

Решение

cache перешел к ApolloServer насколько мне известно, строго используется в контексте RESTDataSource, При извлечении ресурсов из конечной точки REST сервер проверяет Cache-Control заголовок в ответе, и если он существует, будет кэшировать ресурс соответствующим образом. Это означает, что если заголовок max-age=86400ответ будет кэширован с TTL 24 часа, и, пока не истечет срок действия записи в кэше, он будет использоваться вместо вызова того же URL-адреса REST.

Это отличается от механизма кэширования, который вы реализовали, поскольку ваш код кэширует ответ из базы данных. Их цель одинакова, но они работают с разными ресурсами. Единственный способ, которым ваш код будет эффективно дублировать то, что ApolloServer cache уже делает, если вы написали подобное DataSource вместо конечной точки REST.

Хотя оба этих кэша сокращают время, необходимое для обработки вашего ответа на GraphQL (выборка из кэша заметно быстрее, чем из базы данных), кэширование на стороне клиента уменьшает количество запросов, которые должны быть отправлены на ваш сервер. В частности, InMemoryCache позволяет повторно использовать один запрос в разных местах на вашем сайте (например, в различных компонентах React), получая запрос только один раз.

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

Важно отметить, что, хотя ресурсы, кэшированные на стороне сервера, обычно имеют TTL, InMemoryCache не. Вместо этого он использует "политики выборки" для определения поведения отдельных запросов. Это позволяет вам, например, иметь запрос, который всегда выбирается с сервера, независимо от того, что находится в кэше.

Надеюсь, это поможет проиллюстрировать, что кэширование на стороне сервера и на стороне клиента полезно, но совершенно по-разному.

Другие вопросы по тегам