diff --git a/.changeset/fifty-eyes-chew.md b/.changeset/fifty-eyes-chew.md new file mode 100644 index 00000000000..7f4489cfe3e --- /dev/null +++ b/.changeset/fifty-eyes-chew.md @@ -0,0 +1,5 @@ +--- +'@apollo/server-plugin-response-cache': minor +--- + +If the cache you provide to the `cache` option is created with `PrefixingKeyValueCache.cacheDangerouslyDoesNotNeedPrefixesForIsolation` (new in `@apollo/utils.keyvaluecache@2.1.0`), the `fqc:` prefix will not be added to cache keys. diff --git a/.changeset/selfish-buckets-mate.md b/.changeset/selfish-buckets-mate.md new file mode 100644 index 00000000000..c36cf924de1 --- /dev/null +++ b/.changeset/selfish-buckets-mate.md @@ -0,0 +1,5 @@ +--- +'@apollo/server': minor +--- + +If the cache you provide to the `persistedQueries.cache` option is created with `PrefixingKeyValueCache.cacheDangerouslyDoesNotNeedPrefixesForIsolation` (new in `@apollo/utils.keyvaluecache@2.1.0`), the `apq:` prefix will not be added to cache keys. Providing such a cache to `new ApolloServer()` throws an error. diff --git a/.changeset/sour-kiwis-eat.md b/.changeset/sour-kiwis-eat.md new file mode 100644 index 00000000000..34060e3f6cb --- /dev/null +++ b/.changeset/sour-kiwis-eat.md @@ -0,0 +1,5 @@ +--- +'@apollo/server': patch +--- + +For ease of upgrade from the recommended configuration of Apollo Server v3.9+, you can now pass `new ApolloServer({ cache: 'bounded' })`, which is equivalent to not providing the `cache` option (as a bounded cache is now the default in AS4). diff --git a/docs/source/api/apollo-server.mdx b/docs/source/api/apollo-server.mdx index 74ef8958ed0..1063da21cb8 100644 --- a/docs/source/api/apollo-server.mdx +++ b/docs/source/api/apollo-server.mdx @@ -353,7 +353,7 @@ Controls whether to allow [Batching Queries](../workflow/requests/#batching) in A [`KeyValueCache`](https://www.npmjs.com/package/@apollo/utils.keyvaluecache) which Apollo Server uses for several features, including APQs and full response caching. This cache is also available to Apollo Server's plugins. -The default cache is an [`InMemoryLRUCache`](https://www.npmjs.com/package/@apollo/utils.keyvaluecache) with a default size of roughly 30MiB. +The default cache is an [`InMemoryLRUCache`](https://www.npmjs.com/package/@apollo/utils.keyvaluecache) with a default size of roughly 30MiB. (For backwards-compatibility with Apollo Server 3, specifying `cache: 'bounded'` also selects this default bounded cache.) To learn more about configuring Apollo Server's cache, see [Configuring cache backends](../performance/cache-backends). diff --git a/package-lock.json b/package-lock.json index abfc86df2f5..3002645151d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -234,19 +234,7 @@ "node": ">=14" } }, - "node_modules/@apollo/utils.keyvaluecache": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@apollo/utils.keyvaluecache/-/utils.keyvaluecache-2.0.1.tgz", - "integrity": "sha512-F1v3m2pMXPD3rb2+F79qklBBFtNSWssV+8YJIAI0iLxRxoNdDAzfrBFUseUaBaeen/e5mR54QkeNCiq8EvQ/Eg==", - "dependencies": { - "@apollo/utils.logger": "^2.0.0", - "lru-cache": "^7.14.1" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/@apollo/utils.keyvaluecache/node_modules/@apollo/utils.logger": { + "node_modules/@apollo/utils.logger": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@apollo/utils.logger/-/utils.logger-2.0.0.tgz", "integrity": "sha512-o8qYwgV2sYg+PcGKIfwAZaZsQOTEfV8q3mH7Pw8GB/I/Uh2L9iaHdpiKuR++j7oe1K87lFm0z/JAezMOR9CGhg==", @@ -254,14 +242,6 @@ "node": ">=14" } }, - "node_modules/@apollo/utils.keyvaluecache/node_modules/lru-cache": { - "version": "7.14.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.14.1.tgz", - "integrity": "sha512-ysxwsnTKdAx96aTRdhDOCQfDgbHnt8SK0KY8SEjO0wHinhWOFTESbjVCMPbU1uGXg/ch4lifqx0wfjOawU2+WA==", - "engines": { - "node": ">=12" - } - }, "node_modules/@apollo/utils.printwithreducedwhitespace": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@apollo/utils.printwithreducedwhitespace/-/utils.printwithreducedwhitespace-2.0.0.tgz", @@ -13071,7 +13051,7 @@ "dependencies": { "@apollo/usage-reporting-protobuf": "^4.0.0", "@apollo/utils.fetcher": "^2.0.0", - "@apollo/utils.keyvaluecache": "^2.0.1", + "@apollo/utils.keyvaluecache": "^2.1.0", "@apollo/utils.logger": "^2.0.0" }, "peerDependencies": { @@ -13086,14 +13066,26 @@ "node": ">=14" } }, - "packages/gateway-interface/node_modules/@apollo/utils.logger": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@apollo/utils.logger/-/utils.logger-2.0.0.tgz", - "integrity": "sha512-o8qYwgV2sYg+PcGKIfwAZaZsQOTEfV8q3mH7Pw8GB/I/Uh2L9iaHdpiKuR++j7oe1K87lFm0z/JAezMOR9CGhg==", + "packages/gateway-interface/node_modules/@apollo/utils.keyvaluecache": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@apollo/utils.keyvaluecache/-/utils.keyvaluecache-2.1.0.tgz", + "integrity": "sha512-WBNI4H1dGX2fHMk5j4cJo7mlXWn1X6DYCxQ50IvmI7Xv7Y4QKiA5EwbLOCITh9OIZQrVX7L0ASBSgTt6jYx/cg==", + "dependencies": { + "@apollo/utils.logger": "^2.0.0", + "lru-cache": "^7.14.1" + }, "engines": { "node": ">=14" } }, + "packages/gateway-interface/node_modules/lru-cache": { + "version": "7.14.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.14.1.tgz", + "integrity": "sha512-ysxwsnTKdAx96aTRdhDOCQfDgbHnt8SK0KY8SEjO0wHinhWOFTESbjVCMPbU1uGXg/ch4lifqx0wfjOawU2+WA==", + "engines": { + "node": ">=12" + } + }, "packages/integration-testsuite": { "name": "@apollo/server-integration-testsuite", "version": "4.2.2", @@ -13105,7 +13097,7 @@ "@apollo/server-plugin-landing-page-graphql-playground": "^4.0.0", "@apollo/usage-reporting-protobuf": "^4.0.0", "@apollo/utils.createhash": "^2.0.0", - "@apollo/utils.keyvaluecache": "^2.0.1", + "@apollo/utils.keyvaluecache": "^2.1.0", "@josephg/resolvable": "^1.0.1", "body-parser": "^1.20.0", "express": "^4.18.1", @@ -13124,13 +13116,33 @@ "jest": "28.x || 29.x" } }, + "packages/integration-testsuite/node_modules/@apollo/utils.keyvaluecache": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@apollo/utils.keyvaluecache/-/utils.keyvaluecache-2.1.0.tgz", + "integrity": "sha512-WBNI4H1dGX2fHMk5j4cJo7mlXWn1X6DYCxQ50IvmI7Xv7Y4QKiA5EwbLOCITh9OIZQrVX7L0ASBSgTt6jYx/cg==", + "dependencies": { + "@apollo/utils.logger": "^2.0.0", + "lru-cache": "^7.14.1" + }, + "engines": { + "node": ">=14" + } + }, + "packages/integration-testsuite/node_modules/lru-cache": { + "version": "7.14.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.14.1.tgz", + "integrity": "sha512-ysxwsnTKdAx96aTRdhDOCQfDgbHnt8SK0KY8SEjO0wHinhWOFTESbjVCMPbU1uGXg/ch4lifqx0wfjOawU2+WA==", + "engines": { + "node": ">=12" + } + }, "packages/plugin-response-cache": { "name": "@apollo/server-plugin-response-cache", "version": "4.0.3", "license": "MIT", "dependencies": { "@apollo/utils.createhash": "^2.0.0", - "@apollo/utils.keyvaluecache": "^2.0.1" + "@apollo/utils.keyvaluecache": "^2.1.0" }, "engines": { "node": ">=14.16.0" @@ -13140,6 +13152,26 @@ "graphql": "^16.6.0" } }, + "packages/plugin-response-cache/node_modules/@apollo/utils.keyvaluecache": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@apollo/utils.keyvaluecache/-/utils.keyvaluecache-2.1.0.tgz", + "integrity": "sha512-WBNI4H1dGX2fHMk5j4cJo7mlXWn1X6DYCxQ50IvmI7Xv7Y4QKiA5EwbLOCITh9OIZQrVX7L0ASBSgTt6jYx/cg==", + "dependencies": { + "@apollo/utils.logger": "^2.0.0", + "lru-cache": "^7.14.1" + }, + "engines": { + "node": ">=14" + } + }, + "packages/plugin-response-cache/node_modules/lru-cache": { + "version": "7.14.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.14.1.tgz", + "integrity": "sha512-ysxwsnTKdAx96aTRdhDOCQfDgbHnt8SK0KY8SEjO0wHinhWOFTESbjVCMPbU1uGXg/ch4lifqx0wfjOawU2+WA==", + "engines": { + "node": ">=12" + } + }, "packages/server": { "name": "@apollo/server", "version": "4.2.2", @@ -13151,7 +13183,7 @@ "@apollo/utils.createhash": "^2.0.0", "@apollo/utils.fetcher": "^2.0.0", "@apollo/utils.isnodelike": "^2.0.0", - "@apollo/utils.keyvaluecache": "^2.0.1", + "@apollo/utils.keyvaluecache": "^2.1.0", "@apollo/utils.logger": "^2.0.0", "@apollo/utils.usagereporting": "^2.0.0", "@apollo/utils.withrequired": "^2.0.0", @@ -13205,18 +13237,22 @@ "node": ">=14" } }, - "packages/server/node_modules/@apollo/utils.logger": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@apollo/utils.logger/-/utils.logger-2.0.0.tgz", - "integrity": "sha512-o8qYwgV2sYg+PcGKIfwAZaZsQOTEfV8q3mH7Pw8GB/I/Uh2L9iaHdpiKuR++j7oe1K87lFm0z/JAezMOR9CGhg==", + "packages/server/node_modules/@apollo/utils.keyvaluecache": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@apollo/utils.keyvaluecache/-/utils.keyvaluecache-2.1.0.tgz", + "integrity": "sha512-WBNI4H1dGX2fHMk5j4cJo7mlXWn1X6DYCxQ50IvmI7Xv7Y4QKiA5EwbLOCITh9OIZQrVX7L0ASBSgTt6jYx/cg==", + "dependencies": { + "@apollo/utils.logger": "^2.0.0", + "lru-cache": "^7.14.1" + }, "engines": { "node": ">=14" } }, "packages/server/node_modules/lru-cache": { - "version": "7.13.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.13.1.tgz", - "integrity": "sha512-CHqbAq7NFlW3RSnoWXLJBxCWaZVBrfa9UEHId2M3AW8iEBurbqduNexEUCGc3SHc6iCYXNJCDi903LajSVAEPQ==", + "version": "7.14.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.14.1.tgz", + "integrity": "sha512-ysxwsnTKdAx96aTRdhDOCQfDgbHnt8SK0KY8SEjO0wHinhWOFTESbjVCMPbU1uGXg/ch4lifqx0wfjOawU2+WA==", "engines": { "node": ">=12" } @@ -13307,7 +13343,7 @@ "@apollo/utils.createhash": "^2.0.0", "@apollo/utils.fetcher": "^2.0.0", "@apollo/utils.isnodelike": "^2.0.0", - "@apollo/utils.keyvaluecache": "^2.0.1", + "@apollo/utils.keyvaluecache": "^2.1.0", "@apollo/utils.logger": "^2.0.0", "@apollo/utils.usagereporting": "^2.0.0", "@apollo/utils.withrequired": "^2.0.0", @@ -13334,15 +13370,19 @@ "resolved": "https://registry.npmjs.org/@apollo/utils.fetcher/-/utils.fetcher-2.0.0.tgz", "integrity": "sha512-RC0twEwwBKbhk/y4B2X4YEciRG1xoKMgiPy5xQqNMd3pG78sR+ybctG/m7c/8+NaaQOS22UPUCBd6yS6WihBIg==" }, - "@apollo/utils.logger": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@apollo/utils.logger/-/utils.logger-2.0.0.tgz", - "integrity": "sha512-o8qYwgV2sYg+PcGKIfwAZaZsQOTEfV8q3mH7Pw8GB/I/Uh2L9iaHdpiKuR++j7oe1K87lFm0z/JAezMOR9CGhg==" + "@apollo/utils.keyvaluecache": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@apollo/utils.keyvaluecache/-/utils.keyvaluecache-2.1.0.tgz", + "integrity": "sha512-WBNI4H1dGX2fHMk5j4cJo7mlXWn1X6DYCxQ50IvmI7Xv7Y4QKiA5EwbLOCITh9OIZQrVX7L0ASBSgTt6jYx/cg==", + "requires": { + "@apollo/utils.logger": "^2.0.0", + "lru-cache": "^7.14.1" + } }, "lru-cache": { - "version": "7.13.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.13.1.tgz", - "integrity": "sha512-CHqbAq7NFlW3RSnoWXLJBxCWaZVBrfa9UEHId2M3AW8iEBurbqduNexEUCGc3SHc6iCYXNJCDi903LajSVAEPQ==" + "version": "7.14.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.14.1.tgz", + "integrity": "sha512-ysxwsnTKdAx96aTRdhDOCQfDgbHnt8SK0KY8SEjO0wHinhWOFTESbjVCMPbU1uGXg/ch4lifqx0wfjOawU2+WA==" }, "uuid": { "version": "9.0.0", @@ -13356,7 +13396,7 @@ "requires": { "@apollo/usage-reporting-protobuf": "^4.0.0", "@apollo/utils.fetcher": "^2.0.0", - "@apollo/utils.keyvaluecache": "^2.0.1", + "@apollo/utils.keyvaluecache": "^2.1.0", "@apollo/utils.logger": "^2.0.0" }, "dependencies": { @@ -13365,10 +13405,19 @@ "resolved": "https://registry.npmjs.org/@apollo/utils.fetcher/-/utils.fetcher-2.0.0.tgz", "integrity": "sha512-RC0twEwwBKbhk/y4B2X4YEciRG1xoKMgiPy5xQqNMd3pG78sR+ybctG/m7c/8+NaaQOS22UPUCBd6yS6WihBIg==" }, - "@apollo/utils.logger": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@apollo/utils.logger/-/utils.logger-2.0.0.tgz", - "integrity": "sha512-o8qYwgV2sYg+PcGKIfwAZaZsQOTEfV8q3mH7Pw8GB/I/Uh2L9iaHdpiKuR++j7oe1K87lFm0z/JAezMOR9CGhg==" + "@apollo/utils.keyvaluecache": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@apollo/utils.keyvaluecache/-/utils.keyvaluecache-2.1.0.tgz", + "integrity": "sha512-WBNI4H1dGX2fHMk5j4cJo7mlXWn1X6DYCxQ50IvmI7Xv7Y4QKiA5EwbLOCITh9OIZQrVX7L0ASBSgTt6jYx/cg==", + "requires": { + "@apollo/utils.logger": "^2.0.0", + "lru-cache": "^7.14.1" + } + }, + "lru-cache": { + "version": "7.14.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.14.1.tgz", + "integrity": "sha512-ysxwsnTKdAx96aTRdhDOCQfDgbHnt8SK0KY8SEjO0wHinhWOFTESbjVCMPbU1uGXg/ch4lifqx0wfjOawU2+WA==" } } }, @@ -13381,7 +13430,7 @@ "@apollo/server-plugin-landing-page-graphql-playground": "^4.0.0", "@apollo/usage-reporting-protobuf": "^4.0.0", "@apollo/utils.createhash": "^2.0.0", - "@apollo/utils.keyvaluecache": "^2.0.1", + "@apollo/utils.keyvaluecache": "^2.1.0", "@josephg/resolvable": "^1.0.1", "body-parser": "^1.20.0", "express": "^4.18.1", @@ -13390,6 +13439,22 @@ "loglevel": "^1.8.0", "node-fetch": "^2.6.7", "supertest": "^6.2.3" + }, + "dependencies": { + "@apollo/utils.keyvaluecache": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@apollo/utils.keyvaluecache/-/utils.keyvaluecache-2.1.0.tgz", + "integrity": "sha512-WBNI4H1dGX2fHMk5j4cJo7mlXWn1X6DYCxQ50IvmI7Xv7Y4QKiA5EwbLOCITh9OIZQrVX7L0ASBSgTt6jYx/cg==", + "requires": { + "@apollo/utils.logger": "^2.0.0", + "lru-cache": "^7.14.1" + } + }, + "lru-cache": { + "version": "7.14.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.14.1.tgz", + "integrity": "sha512-ysxwsnTKdAx96aTRdhDOCQfDgbHnt8SK0KY8SEjO0wHinhWOFTESbjVCMPbU1uGXg/ch4lifqx0wfjOawU2+WA==" + } } }, "@apollo/server-plugin-landing-page-graphql-playground": { @@ -13404,7 +13469,23 @@ "version": "file:packages/plugin-response-cache", "requires": { "@apollo/utils.createhash": "^2.0.0", - "@apollo/utils.keyvaluecache": "^2.0.1" + "@apollo/utils.keyvaluecache": "^2.1.0" + }, + "dependencies": { + "@apollo/utils.keyvaluecache": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@apollo/utils.keyvaluecache/-/utils.keyvaluecache-2.1.0.tgz", + "integrity": "sha512-WBNI4H1dGX2fHMk5j4cJo7mlXWn1X6DYCxQ50IvmI7Xv7Y4QKiA5EwbLOCITh9OIZQrVX7L0ASBSgTt6jYx/cg==", + "requires": { + "@apollo/utils.logger": "^2.0.0", + "lru-cache": "^7.14.1" + } + }, + "lru-cache": { + "version": "7.14.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.14.1.tgz", + "integrity": "sha512-ysxwsnTKdAx96aTRdhDOCQfDgbHnt8SK0KY8SEjO0wHinhWOFTESbjVCMPbU1uGXg/ch4lifqx0wfjOawU2+WA==" + } } }, "@apollo/usage-reporting-protobuf": { @@ -13433,26 +13514,10 @@ "resolved": "https://registry.npmjs.org/@apollo/utils.isnodelike/-/utils.isnodelike-2.0.0.tgz", "integrity": "sha512-77CiAM2qDXn0haQYrgX0UgrboQykb+bOHaz5p3KKItMwUZ/EFphzuB2vqHvubneIc9dxJcTx2L7MFDswRw/JAQ==" }, - "@apollo/utils.keyvaluecache": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@apollo/utils.keyvaluecache/-/utils.keyvaluecache-2.0.1.tgz", - "integrity": "sha512-F1v3m2pMXPD3rb2+F79qklBBFtNSWssV+8YJIAI0iLxRxoNdDAzfrBFUseUaBaeen/e5mR54QkeNCiq8EvQ/Eg==", - "requires": { - "@apollo/utils.logger": "^2.0.0", - "lru-cache": "^7.14.1" - }, - "dependencies": { - "@apollo/utils.logger": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@apollo/utils.logger/-/utils.logger-2.0.0.tgz", - "integrity": "sha512-o8qYwgV2sYg+PcGKIfwAZaZsQOTEfV8q3mH7Pw8GB/I/Uh2L9iaHdpiKuR++j7oe1K87lFm0z/JAezMOR9CGhg==" - }, - "lru-cache": { - "version": "7.14.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.14.1.tgz", - "integrity": "sha512-ysxwsnTKdAx96aTRdhDOCQfDgbHnt8SK0KY8SEjO0wHinhWOFTESbjVCMPbU1uGXg/ch4lifqx0wfjOawU2+WA==" - } - } + "@apollo/utils.logger": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@apollo/utils.logger/-/utils.logger-2.0.0.tgz", + "integrity": "sha512-o8qYwgV2sYg+PcGKIfwAZaZsQOTEfV8q3mH7Pw8GB/I/Uh2L9iaHdpiKuR++j7oe1K87lFm0z/JAezMOR9CGhg==" }, "@apollo/utils.printwithreducedwhitespace": { "version": "2.0.0", diff --git a/packages/gateway-interface/package.json b/packages/gateway-interface/package.json index 26248ca7e03..99d160e73d1 100644 --- a/packages/gateway-interface/package.json +++ b/packages/gateway-interface/package.json @@ -20,7 +20,7 @@ "dependencies": { "@apollo/utils.fetcher": "^2.0.0", "@apollo/utils.logger": "^2.0.0", - "@apollo/utils.keyvaluecache": "^2.0.1", + "@apollo/utils.keyvaluecache": "^2.1.0", "@apollo/usage-reporting-protobuf": "^4.0.0" }, "peerDependencies": { diff --git a/packages/integration-testsuite/package.json b/packages/integration-testsuite/package.json index 36bf686c18d..4e541c4a149 100644 --- a/packages/integration-testsuite/package.json +++ b/packages/integration-testsuite/package.json @@ -30,7 +30,7 @@ "@apollo/client": "^3.6.9", "@apollo/server": "4.2.2", "@apollo/server-plugin-landing-page-graphql-playground": "^4.0.0", - "@apollo/utils.keyvaluecache": "^2.0.1", + "@apollo/utils.keyvaluecache": "^2.1.0", "@apollo/utils.createhash": "^2.0.0", "@apollo/usage-reporting-protobuf": "^4.0.0", "@josephg/resolvable": "^1.0.1", diff --git a/packages/plugin-response-cache/package.json b/packages/plugin-response-cache/package.json index b827cc7ef73..e6351388dd1 100644 --- a/packages/plugin-response-cache/package.json +++ b/packages/plugin-response-cache/package.json @@ -30,7 +30,7 @@ }, "dependencies": { "@apollo/utils.createhash": "^2.0.0", - "@apollo/utils.keyvaluecache": "^2.0.1" + "@apollo/utils.keyvaluecache": "^2.1.0" }, "peerDependencies": { "@apollo/server": "^4.0.1", diff --git a/packages/server/package.json b/packages/server/package.json index 227241e4d73..14b679b3434 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -90,7 +90,7 @@ "@apollo/utils.createhash": "^2.0.0", "@apollo/utils.fetcher": "^2.0.0", "@apollo/utils.isnodelike": "^2.0.0", - "@apollo/utils.keyvaluecache": "^2.0.1", + "@apollo/utils.keyvaluecache": "^2.1.0", "@apollo/utils.logger": "^2.0.0", "@apollo/utils.usagereporting": "^2.0.0", "@apollo/utils.withrequired": "^2.0.0", diff --git a/packages/server/src/ApolloServer.ts b/packages/server/src/ApolloServer.ts index 13f88e5f5ee..64ab795d685 100644 --- a/packages/server/src/ApolloServer.ts +++ b/packages/server/src/ApolloServer.ts @@ -98,6 +98,12 @@ export type SchemaDerivedData = { // versions of operations in-memory, allowing subsequent parses/validates // on the same operation to be executed immediately. documentStore: DocumentStore | null; + // Prefix for keys in the DocumentStore if a custom one is provided (to + // separate the cache for different schema versions). This is vital to + // security so we do it explicitly so that + // PrefixingKeyValueCache.cacheDangerouslyDoesNotNeedPrefixesForIsolation + // doesn't affect it. + documentStoreKeyPrefix: string; }; type RunningServerState = { @@ -214,6 +220,19 @@ export class ApolloServer { const isDev = nodeEnv !== 'production'; + if ( + config.cache && + config.cache !== 'bounded' && + PrefixingKeyValueCache.prefixesAreUnnecessaryForIsolation(config.cache) + ) { + throw new Error( + 'You cannot pass a cache returned from ' + + '`PrefixingKeyValueCache.cacheDangerouslyDoesNotNeedPrefixesForIsolation`' + + 'to `new ApolloServer({ cache })`, because Apollo Server may use it for ' + + 'multiple features whose cache keys must be distinct from each other.', + ); + } + const state: ServerState = config.gateway ? // ApolloServer has been initialized but we have not yet tried to load the // schema from the gateway. That will wait until `start()` or @@ -256,7 +275,12 @@ export class ApolloServer { const introspectionEnabled = config.introspection ?? isDev; - this.cache = config.cache ?? new InMemoryLRUCache(); + // We continue to allow 'bounded' for backwards-compatibility with the AS3.9 + // API. + this.cache = + config.cache === undefined || config.cache === 'bounded' + ? new InMemoryLRUCache() + : config.cache; // Note that we avoid calling methods on `this` before `this.internals` is assigned // (thus a bunch of things being static methods above). @@ -682,7 +706,7 @@ export class ApolloServer { // missing/undefined means use the default (creating a new one each // time). // defined means wrap this one in a random prefix for each new schema. - providedUnprefixedDocumentStore: DocumentStore | null | undefined, + providedDocumentStore: DocumentStore | null | undefined, ): SchemaDerivedData { // Instead of waiting for the first operation execution against the schema // to find out if it's a valid schema or not, check right now. In the @@ -703,14 +727,10 @@ export class ApolloServer { // new schema. If we're using a user-provided DocumentStore, then we use a // random prefix each time we get a new schema. documentStore: - providedUnprefixedDocumentStore === undefined + providedDocumentStore === undefined ? new InMemoryLRUCache() - : providedUnprefixedDocumentStore === null - ? null - : new PrefixingKeyValueCache( - providedUnprefixedDocumentStore, - `${uuid.v4()}:`, - ), + : providedDocumentStore, + documentStoreKeyPrefix: providedDocumentStore ? `${uuid.v4()}:` : '', }; } diff --git a/packages/server/src/externalTypes/constructor.ts b/packages/server/src/externalTypes/constructor.ts index 4a73677df8f..e6c629e04d0 100644 --- a/packages/server/src/externalTypes/constructor.ts +++ b/packages/server/src/externalTypes/constructor.ts @@ -84,7 +84,7 @@ interface ApolloServerOptionsBase { rootValue?: ((parsedQuery: DocumentNode) => unknown) | unknown; validationRules?: Array; fieldResolver?: GraphQLFieldResolver; - cache?: KeyValueCache; + cache?: KeyValueCache | 'bounded'; includeStacktraceInErrorResponses?: boolean; logger?: Logger; allowBatchedHttpRequests?: boolean; diff --git a/packages/server/src/requestPipeline.ts b/packages/server/src/requestPipeline.ts index a40406c20b7..663e08a37d4 100644 --- a/packages/server/src/requestPipeline.ts +++ b/packages/server/src/requestPipeline.ts @@ -202,7 +202,7 @@ export async function processGraphQLRequest( if (schemaDerivedData.documentStore) { try { requestContext.document = await schemaDerivedData.documentStore.get( - queryHash, + schemaDerivedData.documentStoreKeyPrefix + queryHash, ); } catch (err: unknown) { server.logger.warn( @@ -271,7 +271,10 @@ export async function processGraphQLRequest( // `Promise.resolve` invocation, it seems that the underlying cache store // is returning a non-native `Promise` (e.g. Bluebird, etc.). Promise.resolve( - schemaDerivedData.documentStore.set(queryHash, requestContext.document), + schemaDerivedData.documentStore.set( + schemaDerivedData.documentStoreKeyPrefix + queryHash, + requestContext.document, + ), ).catch((err) => server.logger.warn( 'Could not store validated document. ' + err?.message || err,