From 1aad6e2d3a5b7a4061da768be8256bb2e4dbf55b Mon Sep 17 00:00:00 2001 From: Jesse Rosenberger Date: Thu, 19 Dec 2019 16:59:16 +0200 Subject: [PATCH 1/8] Use common interface for all `KeyValueCache`'s `options` for `set`. Previously, these were all respecifying their own interface for the options, which are the options which are passed to the `set` method when storing an entry in those caches. These are shared interfaces, and they all only allow a `ttl?: number`. --- packages/apollo-server-cache-memcached/src/index.ts | 9 ++++++--- packages/apollo-server-cache-redis/src/RedisCache.ts | 9 ++++++--- .../apollo-server-cache-redis/src/RedisClusterCache.ts | 6 +++--- packages/apollo-server-caching/src/KeyValueCache.ts | 2 +- .../apollo-server-caching/src/PrefixingKeyValueCache.ts | 4 ++-- packages/apollo-server-caching/src/index.ts | 6 +++++- 6 files changed, 23 insertions(+), 13 deletions(-) diff --git a/packages/apollo-server-cache-memcached/src/index.ts b/packages/apollo-server-cache-memcached/src/index.ts index 5df0de37b85..aa6ec5267ae 100644 --- a/packages/apollo-server-cache-memcached/src/index.ts +++ b/packages/apollo-server-cache-memcached/src/index.ts @@ -1,11 +1,14 @@ -import { TestableKeyValueCache } from 'apollo-server-caching'; +import { + TestableKeyValueCache, + KeyValueCacheSetOptions, +} from 'apollo-server-caching'; import Memcached from 'memcached'; import { promisify } from 'util'; export class MemcachedCache implements TestableKeyValueCache { // FIXME: Replace any with proper promisified type readonly client: any; - readonly defaultSetOptions = { + readonly defaultSetOptions: KeyValueCacheSetOptions = { ttl: 300, }; @@ -23,7 +26,7 @@ export class MemcachedCache implements TestableKeyValueCache { async set( key: string, value: string, - options?: { ttl?: number }, + options?: KeyValueCacheSetOptions, ): Promise { const { ttl } = Object.assign({}, this.defaultSetOptions, options); await this.client.set(key, value, ttl); diff --git a/packages/apollo-server-cache-redis/src/RedisCache.ts b/packages/apollo-server-cache-redis/src/RedisCache.ts index 56e58562015..95a9130ec05 100644 --- a/packages/apollo-server-cache-redis/src/RedisCache.ts +++ b/packages/apollo-server-cache-redis/src/RedisCache.ts @@ -1,10 +1,13 @@ -import { TestableKeyValueCache } from 'apollo-server-caching'; +import { + TestableKeyValueCache, + KeyValueCacheSetOptions, +} from 'apollo-server-caching'; import Redis, { RedisOptions } from 'ioredis'; import DataLoader from 'dataloader'; export class RedisCache implements TestableKeyValueCache { readonly client: any; - readonly defaultSetOptions = { + readonly defaultSetOptions: KeyValueCacheSetOptions = { ttl: 300, }; @@ -22,7 +25,7 @@ export class RedisCache implements TestableKeyValueCache { async set( key: string, value: string, - options?: { ttl?: number }, + options?: KeyValueCacheSetOptions, ): Promise { const { ttl } = Object.assign({}, this.defaultSetOptions, options); await this.client.set(key, value, 'EX', ttl); diff --git a/packages/apollo-server-cache-redis/src/RedisClusterCache.ts b/packages/apollo-server-cache-redis/src/RedisClusterCache.ts index d265e193db0..32402716e7a 100644 --- a/packages/apollo-server-cache-redis/src/RedisClusterCache.ts +++ b/packages/apollo-server-cache-redis/src/RedisClusterCache.ts @@ -1,4 +1,4 @@ -import { KeyValueCache } from 'apollo-server-caching'; +import { KeyValueCache, KeyValueCacheSetOptions } from 'apollo-server-caching'; import Redis, { ClusterOptions, ClusterNode, @@ -8,7 +8,7 @@ import DataLoader from 'dataloader'; export class RedisClusterCache implements KeyValueCache { readonly client: any; - readonly defaultSetOptions = { + readonly defaultSetOptions: KeyValueCacheSetOptions = { ttl: 300, }; @@ -27,7 +27,7 @@ export class RedisClusterCache implements KeyValueCache { async set( key: string, data: string, - options?: { ttl?: number }, + options?: KeyValueCacheSetOptions, ): Promise { const { ttl } = Object.assign({}, this.defaultSetOptions, options); await this.client.set(key, data, 'EX', ttl); diff --git a/packages/apollo-server-caching/src/KeyValueCache.ts b/packages/apollo-server-caching/src/KeyValueCache.ts index 3dd1616379b..2a1b6671e24 100644 --- a/packages/apollo-server-caching/src/KeyValueCache.ts +++ b/packages/apollo-server-caching/src/KeyValueCache.ts @@ -1,5 +1,5 @@ /** Options for {@link KeyValueCache.set} */ -interface KeyValueCacheSetOptions { +export interface KeyValueCacheSetOptions { /** * Specified in **seconds**, the time-to-live (TTL) value limits the lifespan * of the data being stored in the cache. diff --git a/packages/apollo-server-caching/src/PrefixingKeyValueCache.ts b/packages/apollo-server-caching/src/PrefixingKeyValueCache.ts index ffa4c8f04a0..039f4a07679 100644 --- a/packages/apollo-server-caching/src/PrefixingKeyValueCache.ts +++ b/packages/apollo-server-caching/src/PrefixingKeyValueCache.ts @@ -1,4 +1,4 @@ -import { KeyValueCache } from './KeyValueCache'; +import { KeyValueCache, KeyValueCacheSetOptions } from './KeyValueCache'; // PrefixingKeyValueCache wraps another cache and adds a prefix to all keys used // by all operations. This allows multiple features to share the same @@ -16,7 +16,7 @@ export class PrefixingKeyValueCache implements KeyValueCache { get(key: string) { return this.wrapped.get(this.prefix + key); } - set(key: string, value: V, options?: { ttl?: number }) { + set(key: string, value: V, options?: KeyValueCacheSetOptions) { return this.wrapped.set(this.prefix + key, value, options); } delete(key: string) { diff --git a/packages/apollo-server-caching/src/index.ts b/packages/apollo-server-caching/src/index.ts index bd49bc740cf..cd94a872b38 100644 --- a/packages/apollo-server-caching/src/index.ts +++ b/packages/apollo-server-caching/src/index.ts @@ -1,3 +1,7 @@ -export { KeyValueCache, TestableKeyValueCache } from './KeyValueCache'; +export { + KeyValueCache, + TestableKeyValueCache, + KeyValueCacheSetOptions, +} from './KeyValueCache'; export { InMemoryLRUCache } from './InMemoryLRUCache'; export { PrefixingKeyValueCache } from './PrefixingKeyValueCache'; From a7fd8220ee85eb9f5fa0e07fe008f9e75adceb4f Mon Sep 17 00:00:00 2001 From: Jesse Rosenberger Date: Thu, 19 Dec 2019 17:01:55 +0200 Subject: [PATCH 2/8] Change the `ioredis` test mock to not expire records lacking a `ttl`. Most cache stores, including Redis, support the notion of not applying a TTL specifier on a cache record, thus allowing it to survive as long as possible. Of course, other factors may cause the record to be evicted (e.g. out of memory on that node, need to make room for objects which are hotter, etc.), those decisions are ultimately left up to the controller of those caches. This paves the way for the next commits. --- .../apollo-server-cache-redis/src/__mocks__/ioredis.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/apollo-server-cache-redis/src/__mocks__/ioredis.ts b/packages/apollo-server-cache-redis/src/__mocks__/ioredis.ts index d5c2c7a98ef..61a38a55f19 100644 --- a/packages/apollo-server-cache-redis/src/__mocks__/ioredis.ts +++ b/packages/apollo-server-cache-redis/src/__mocks__/ioredis.ts @@ -22,9 +22,11 @@ const setKey = (key, value, type, ttl) => { value, ttl, }; - setTimeout(() => { - delete keyValue[key]; - }, ttl * 1000); + if (ttl) { + setTimeout(() => { + delete keyValue[key]; + }, ttl * 1000); + } return Promise.resolve(true); }; From 07a2f598eef7c454563a1c6f75e9b3e882d2f51b Mon Sep 17 00:00:00 2001 From: Jesse Rosenberger Date: Thu, 19 Dec 2019 17:04:31 +0200 Subject: [PATCH 3/8] Make mock caches more testable by defining their methods as `jest.fn()`s. This will allow us to determine which have been set from tests which need to assert those properties. --- .../src/index.ts | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/packages/apollo-server-integration-testsuite/src/index.ts b/packages/apollo-server-integration-testsuite/src/index.ts index 94be1b7dc33..99a4d830320 100644 --- a/packages/apollo-server-integration-testsuite/src/index.ts +++ b/packages/apollo-server-integration-testsuite/src/index.ts @@ -1226,16 +1226,20 @@ export default (createApp: CreateAppFunc, destroyApp?: DestroyAppFunc) => { Parameters >; - beforeEach(async () => { + function createMockCache() { const map = new Map(); - const cache = { - set: async (key, val) => { + return { + set: jest.fn(async (key, val) => { await map.set(key, val); - }, - get: async key => map.get(key), - delete: async key => map.delete(key), + }), + get: jest.fn(async key => map.get(key)), + delete: jest.fn(async key => map.delete(key)), }; + } + + beforeEach(async () => { didEncounterErrors = jest.fn(); + const cache = createMockCache(); app = await createApp({ graphqlOptions: { schema, From 8d5672fe8a04eb01f90800bf6eb35dd6676842ee Mon Sep 17 00:00:00 2001 From: Jesse Rosenberger Date: Thu, 19 Dec 2019 17:05:29 +0200 Subject: [PATCH 4/8] Preserve other non-`cache` properties on this APQ cache configuration. This was already the case prior to 875944ea8358caa2140e6f7fff861f7a8f0149e4, however the rejiggering in that PR removed that functionality, causing any other properties present on the cache configuration to be dropped. The original implementation can be seen here: https://github.com/apollographql/apollo-server/commit/875944ea#diff-3467ccc78fbd796513acd747ff2110a5L212-L216 This was frustrating to sort out! --- packages/apollo-server-core/src/ApolloServer.ts | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/packages/apollo-server-core/src/ApolloServer.ts b/packages/apollo-server-core/src/ApolloServer.ts index 1d5ad694a0f..9da7462c125 100644 --- a/packages/apollo-server-core/src/ApolloServer.ts +++ b/packages/apollo-server-core/src/ApolloServer.ts @@ -243,13 +243,14 @@ export class ApolloServerBase { } if (requestOptions.persistedQueries !== false) { + const { + cache: apqCache = requestOptions.cache!, + ...apqOtherOptions + } = requestOptions.persistedQueries || Object.create(null); + requestOptions.persistedQueries = { - cache: new PrefixingKeyValueCache( - (requestOptions.persistedQueries && - requestOptions.persistedQueries.cache) || - requestOptions.cache!, - APQ_CACHE_PREFIX, - ), + cache: new PrefixingKeyValueCache(apqCache, APQ_CACHE_PREFIX), + ...apqOtherOptions, }; } else { // the user does not want to use persisted queries, so we remove the field From 83a840042424459bc612de32ca3a508560886c23 Mon Sep 17 00:00:00 2001 From: Jesse Rosenberger Date: Thu, 19 Dec 2019 17:09:00 +0200 Subject: [PATCH 5/8] Allow `KeyValueCache` implementations to not specify a TTL by using `null`. Rather than defaulting to a behavior of not applying a TTL unless desired, all of the current cache implementations specify a default TTL of 300. This change introduces a specific notion of an intent to not apply a TTL (and instead leave the eviction decision to the cache controller) by introducing a concept of `null` for the TTL which will allow individual subclasses of `KeyValueCache` to react accordingly. For example, in Memcached, this requires setting the TTL to 0, but in Redis, it requires omitting arguments entirely. This preserves backwards compatible behavior for existing cache configurations by levering this new `null`ability. --- packages/apollo-server-cache-memcached/src/index.ts | 8 +++++++- packages/apollo-server-cache-redis/src/RedisCache.ts | 8 +++++++- .../src/RedisClusterCache.ts | 8 +++++++- packages/apollo-server-caching/src/KeyValueCache.ts | 2 +- .../apollo-server-caching/src/__tests__/testsuite.ts | 11 +++++++++++ 5 files changed, 33 insertions(+), 4 deletions(-) diff --git a/packages/apollo-server-cache-memcached/src/index.ts b/packages/apollo-server-cache-memcached/src/index.ts index aa6ec5267ae..25d0f5ced98 100644 --- a/packages/apollo-server-cache-memcached/src/index.ts +++ b/packages/apollo-server-cache-memcached/src/index.ts @@ -29,7 +29,13 @@ export class MemcachedCache implements TestableKeyValueCache { options?: KeyValueCacheSetOptions, ): Promise { const { ttl } = Object.assign({}, this.defaultSetOptions, options); - await this.client.set(key, value, ttl); + if (typeof ttl === 'number') { + await this.client.set(key, value, ttl); + } else { + // In Memcached, zero indicates no specific expiration time. Of course, + // it may be purged from the cache for other reasons as deemed necessary. + await this.client.set(key, value, 0); + } } async get(key: string): Promise { diff --git a/packages/apollo-server-cache-redis/src/RedisCache.ts b/packages/apollo-server-cache-redis/src/RedisCache.ts index 95a9130ec05..b45998dea98 100644 --- a/packages/apollo-server-cache-redis/src/RedisCache.ts +++ b/packages/apollo-server-cache-redis/src/RedisCache.ts @@ -28,7 +28,13 @@ export class RedisCache implements TestableKeyValueCache { options?: KeyValueCacheSetOptions, ): Promise { const { ttl } = Object.assign({}, this.defaultSetOptions, options); - await this.client.set(key, value, 'EX', ttl); + if (typeof ttl === 'number') { + await this.client.set(key, value, 'EX', ttl); + } else { + // We'll leave out the EXpiration when no value is specified. Of course, + // it may be purged from the cache for other reasons as deemed necessary. + await this.client.set(key, value); + } } async get(key: string): Promise { diff --git a/packages/apollo-server-cache-redis/src/RedisClusterCache.ts b/packages/apollo-server-cache-redis/src/RedisClusterCache.ts index 32402716e7a..79bd73c83f0 100644 --- a/packages/apollo-server-cache-redis/src/RedisClusterCache.ts +++ b/packages/apollo-server-cache-redis/src/RedisClusterCache.ts @@ -30,7 +30,13 @@ export class RedisClusterCache implements KeyValueCache { options?: KeyValueCacheSetOptions, ): Promise { const { ttl } = Object.assign({}, this.defaultSetOptions, options); - await this.client.set(key, data, 'EX', ttl); + if (typeof ttl === 'number') { + await this.client.set(key, data, 'EX', ttl); + } else { + // We'll leave out the EXpiration when no value is specified. Of course, + // it may be purged from the cache for other reasons as deemed necessary. + await this.client.set(key, data); + } } async get(key: string): Promise { diff --git a/packages/apollo-server-caching/src/KeyValueCache.ts b/packages/apollo-server-caching/src/KeyValueCache.ts index 2a1b6671e24..88c580ea50c 100644 --- a/packages/apollo-server-caching/src/KeyValueCache.ts +++ b/packages/apollo-server-caching/src/KeyValueCache.ts @@ -4,7 +4,7 @@ export interface KeyValueCacheSetOptions { * Specified in **seconds**, the time-to-live (TTL) value limits the lifespan * of the data being stored in the cache. */ - ttl?: number + ttl?: number | null }; export interface KeyValueCache { diff --git a/packages/apollo-server-caching/src/__tests__/testsuite.ts b/packages/apollo-server-caching/src/__tests__/testsuite.ts index c4f8bbd67df..722b6e36923 100644 --- a/packages/apollo-server-caching/src/__tests__/testsuite.ts +++ b/packages/apollo-server-caching/src/__tests__/testsuite.ts @@ -54,6 +54,17 @@ export function testKeyValueCache_Expiration( expect(await keyValueCache.get('short')).toBeUndefined(); expect(await keyValueCache.get('long')).toBeUndefined(); }); + + it('does not expire when ttl is null', async () => { + await keyValueCache.set('forever', 'yours', { ttl: null }); + expect(await keyValueCache.get('forever')).toBe('yours'); + advanceTimeBy(1500); + jest.advanceTimersByTime(1500); + expect(await keyValueCache.get('forever')).toBe('yours'); + advanceTimeBy(4000); + jest.advanceTimersByTime(4000); + expect(await keyValueCache.get('forever')).toBe('yours'); + }); }); } From d025580fa64840f8ee3cbcf7ee80a6061b09aa01 Mon Sep 17 00:00:00 2001 From: Jesse Rosenberger Date: Thu, 19 Dec 2019 17:12:18 +0200 Subject: [PATCH 6/8] Allow the APQ cache to be configured with a different TTL value. Previously, there was no way to specify this value using any of our `KeyValueCache` implementations - whether Memcached, Redis, or otherwise. This provides that ability by setting a `ttlSeconds` to a numeric or `null` (to specify no TTL). --- .../apollo-server-core/src/graphqlOptions.ts | 8 +++ .../apollo-server-core/src/requestPipeline.ts | 15 ++++- .../src/index.ts | 57 +++++++++++++++++++ 3 files changed, 77 insertions(+), 3 deletions(-) diff --git a/packages/apollo-server-core/src/graphqlOptions.ts b/packages/apollo-server-core/src/graphqlOptions.ts index 19b0574469c..f7ab5403241 100644 --- a/packages/apollo-server-core/src/graphqlOptions.ts +++ b/packages/apollo-server-core/src/graphqlOptions.ts @@ -69,6 +69,14 @@ export type DataSources = { export interface PersistedQueryOptions { cache: KeyValueCache; + /** + * Specified in **seconds**, this time-to-live (TTL) value limits the lifespan + * of how long the persisted query should be cached. To specify a desired + * lifespan of "infinite", set this to `null`, in which case the eviction will + * be determined by the cache's eviction policy, but the record will never + * simply expire. + */ + ttlSeconds?: number | null; } export default GraphQLServerOptions; diff --git a/packages/apollo-server-core/src/requestPipeline.ts b/packages/apollo-server-core/src/requestPipeline.ts index 0986c741682..2f98aa7a8b8 100644 --- a/packages/apollo-server-core/src/requestPipeline.ts +++ b/packages/apollo-server-core/src/requestPipeline.ts @@ -330,9 +330,18 @@ export async function processGraphQLRequest( // an error) and not actually write, we'll write to the cache if it was // determined earlier in the request pipeline that we should do so. if (metrics.persistedQueryRegister && persistedQueryCache) { - Promise.resolve(persistedQueryCache.set(queryHash, query)).catch( - console.warn, - ); + Promise.resolve( + persistedQueryCache.set( + queryHash, + query, + config.persistedQueries && + typeof config.persistedQueries.ttlSeconds !== 'undefined' + ? { + ttl: config.persistedQueries.ttlSeconds, + } + : Object.create(null), + ), + ).catch(console.warn); } let response: GraphQLResponse | null = await dispatcher.invokeHooksUntilNonNull( diff --git a/packages/apollo-server-integration-testsuite/src/index.ts b/packages/apollo-server-integration-testsuite/src/index.ts index 99a4d830320..ad9a27e9dd4 100644 --- a/packages/apollo-server-integration-testsuite/src/index.ts +++ b/packages/apollo-server-integration-testsuite/src/index.ts @@ -1257,6 +1257,63 @@ export default (createApp: CreateAppFunc, destroyApp?: DestroyAppFunc) => { }); }); + it('when ttlSeconds is set, passes ttl to the apq cache set call', async () => { + const cache = createMockCache(); + app = await createApp({ + graphqlOptions: { + schema, + persistedQueries: { + cache: cache, + ttlSeconds: 900, + }, + }, + }); + + await request(app) + .post('/graphql') + .send({ + extensions, + query, + }); + + expect(cache.set).toHaveBeenCalledWith( + expect.stringMatching(/^apq:/), + '{testString}', + expect.objectContaining({ + ttl: 900, + }), + ); + }); + + it('when ttlSeconds is unset, ttl is not passed to apq cache', + async () => { + const cache = createMockCache(); + app = await createApp({ + graphqlOptions: { + schema, + persistedQueries: { + cache: cache, + }, + }, + }); + + await request(app) + .post('/graphql') + .send({ + extensions, + query, + }); + + expect(cache.set).toHaveBeenCalledWith( + expect.stringMatching(/^apq:/), + '{testString}', + expect.not.objectContaining({ + ttl: 900, + }), + ); + } + ); + it('errors when version is not specified', async () => { const result = await request(app) .get('/graphql') From 0da9a7d86f359a9fb7e765c3e9fb08920dd43c61 Mon Sep 17 00:00:00 2001 From: Jesse Rosenberger Date: Fri, 27 Dec 2019 13:45:52 +0200 Subject: [PATCH 7/8] Add CHANGELOG.md for #3623. --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7c30c46b282..84ce2c33ef2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ The version headers in this history reflect the versions of Apollo Server itself - `apollo-server-core`: Upgrade TS to 3.7.3 [#3618](https://github.com/apollographql/apollo-server/pull/3618) - `apollo-server-cloud-functions`: Transmit CORS headers on `OPTIONS` request. [PR #3557](https://github.com/apollographql/apollo-server/pull/3557) - `apollo-server-caching`: De-compose options interface for `KeyValueCache.prototype.set` to accommodate better TSDoc annotations for its properties (e.g. to specify that `ttl` is defined in _seconds_). [PR #3619](https://github.com/apollographql/apollo-server/pull/3619) +- `apollo-server-core`, `apollo-server-caching`: Introduce a `ttl` property, specified in seconds, on the options for automated persisted queries (APQ) which applies specific TTL settings to the cache `set`s during APQ registration. Previously, all APQ cache records were set to 300 seconds. Additionally, this adds support (to the underlying `apollo-server-caching` mechanisms) for a time-to-live (TTL) value of `null` which, when supported by the cache implementation, skips the assignment of a TTL value altogether. This allows the cache's controller to determine when eviction happens (e.g. cache forever, and purge least recently used when the cache is full), which may be desireable for network cache stores (e.g. Memcached, Redis). [PR #3623](https://github.com/apollographql/apollo-server/pull/3623) ### v2.9.14 From eed31f0ac72e6c9e7e6ba35c10cfb8fa4ccc53cd Mon Sep 17 00:00:00 2001 From: Jesse Rosenberger Date: Fri, 27 Dec 2019 13:46:52 +0200 Subject: [PATCH 8/8] Rename `ttlSeconds` to `ttl` for consistency with existing parameters. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit While I do appreciate the clarity of the unit being included in the parameter, I noted some thoughts here: https://github.com/apollographql/apollo-server/pull/3623#discussion_r360348888 As an additional consideration for using `ttl` rather than `ttlSeconds`, one could imagine an iteration on this parameter's flexibility which could support string-based (e.g. ISO 8601, human-readable à la moment) values which would themselves conflict (in terms of compatibility without a parameter rename) with having a unit baked into the name. --- packages/apollo-server-core/src/graphqlOptions.ts | 2 +- packages/apollo-server-core/src/requestPipeline.ts | 4 ++-- packages/apollo-server-integration-testsuite/src/index.ts | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/apollo-server-core/src/graphqlOptions.ts b/packages/apollo-server-core/src/graphqlOptions.ts index f7ab5403241..19015c93bb2 100644 --- a/packages/apollo-server-core/src/graphqlOptions.ts +++ b/packages/apollo-server-core/src/graphqlOptions.ts @@ -76,7 +76,7 @@ export interface PersistedQueryOptions { * be determined by the cache's eviction policy, but the record will never * simply expire. */ - ttlSeconds?: number | null; + ttl?: number | null; } export default GraphQLServerOptions; diff --git a/packages/apollo-server-core/src/requestPipeline.ts b/packages/apollo-server-core/src/requestPipeline.ts index 2f98aa7a8b8..b40f8bdfdde 100644 --- a/packages/apollo-server-core/src/requestPipeline.ts +++ b/packages/apollo-server-core/src/requestPipeline.ts @@ -335,9 +335,9 @@ export async function processGraphQLRequest( queryHash, query, config.persistedQueries && - typeof config.persistedQueries.ttlSeconds !== 'undefined' + typeof config.persistedQueries.ttl !== 'undefined' ? { - ttl: config.persistedQueries.ttlSeconds, + ttl: config.persistedQueries.ttl, } : Object.create(null), ), diff --git a/packages/apollo-server-integration-testsuite/src/index.ts b/packages/apollo-server-integration-testsuite/src/index.ts index ad9a27e9dd4..21a65212ca9 100644 --- a/packages/apollo-server-integration-testsuite/src/index.ts +++ b/packages/apollo-server-integration-testsuite/src/index.ts @@ -1264,7 +1264,7 @@ export default (createApp: CreateAppFunc, destroyApp?: DestroyAppFunc) => { schema, persistedQueries: { cache: cache, - ttlSeconds: 900, + ttl: 900, }, }, });