diff --git a/CHANGELOG.md b/CHANGELOG.md index b9b32a3c9d4..a01b83cb50c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ The version headers in this history reflect the versions of Apollo Server itself - Move TContext generic from requestDidStart method to ApolloServerPlugin Interface [#3525](https://github.com/apollographql/apollo-server/pull/3525) - `apollo-server-express`: Support `CorsOptionsDelegate` type on `cors` parameter to `applyMiddleware`, to align with the supported type of the underlying [`cors`](https://npm.im/cors) middleware [itself](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/31483b781ac30f98bdf4d40a517e921f2fc2ce37/types/cors/index.d.ts#L32). [PR #3613](https://github.com/apollographql/apollo-server/pull/3613) - `apollo-server-core`: Allow asynchronous initialization of datasources: the `initialize` method on datasources may now return a Promise, which will be settled before any resolvers are called. [#3639](https://github.com/apollographql/apollo-server/pull/3639) +- `apollo-server-core`: experimental: Allow configuration of the parsed/validated document store by introducing an `experimental_approximateDocumentStoreMiB` property to the `ApolloServer` constructor options which overrides the default cache size of 30MiB. [#3755](https://github.com/apollographql/apollo-server/pull/3755) ### v2.9.16 diff --git a/docs/source/api/apollo-gateway.mdx b/docs/source/api/apollo-gateway.mdx index d708a447f9e..1fc688e8a4a 100644 --- a/docs/source/api/apollo-gateway.mdx +++ b/docs/source/api/apollo-gateway.mdx @@ -91,6 +91,18 @@ example of using `ApolloGateway`, see [Implementing a federated graph](/federati If `true`, the gateway logs startup messages, along with the query plan for each incoming request. The default value is `false`. + * `experimental_approximateQueryPlanStoreMiB`: `number` + + > **This property is experimental.** It may be removed or change at any time, even within a patch release. + + When set, this sets the approximate size of the query plan store (in MiB). + This cache is used to save query plans for re-use on subsequent queries + which resolve to the same `queryHash` (a SHA-256 of incoming operation). + + When this property is omitted, the cache is still enabled with a default + size of 30MiB, which is generally sufficient unless the server is + processing a high number of unique operations. + #### Returns An `ApolloGateway` instance, which you then pass as the `gateway` configuration option to the `ApolloServer` constructor, like so: diff --git a/docs/source/api/apollo-server.md b/docs/source/api/apollo-server.md index 38ce61dc0e2..4dac689d772 100644 --- a/docs/source/api/apollo-server.md +++ b/docs/source/api/apollo-server.md @@ -144,6 +144,19 @@ new ApolloServer({ Pass the integration-specific CORS options. `false` removes the CORS middleware and `true` uses the defaults. This option is only available to `apollo-server`. For other server integrations, place `cors` inside of `applyMiddleware`. +* `experimental_approximateDocumentStoreSizeMiB`: `number` + + > **This property is experimental.** It may be removed or change at any time, even within a patch release. + + When set, this sets the approximate size of the parsed/validated document + store (in MiB). This cache is used to save the already parsed and validated + `DocumentNode`s for re-use on subsequent queries which resolve to the same + `queryHash` (a SHA-256 of incoming operation). + + When this property is omitted, the cache is still enabled with a default + size of 30MiB, which is generally sufficient unless the server is processing + a high number of unique operations. + #### Returns `ApolloServer` diff --git a/packages/apollo-gateway/CHANGELOG.md b/packages/apollo-gateway/CHANGELOG.md index 12fdf842378..f52baa14c54 100644 --- a/packages/apollo-gateway/CHANGELOG.md +++ b/packages/apollo-gateway/CHANGELOG.md @@ -7,6 +7,7 @@ * Reduce interface expansion for types contained to a single service [#3582](https://github.com/apollographql/apollo-server/pull/3582) * Instantiate one `CachedFetcher` per gateway instance. This resolves a condition where multiple federated gateways would utilize the same cache store could result in an `Expected undefined to be a GraphQLSchema` error. [#3704](https://github.com/apollographql/apollo-server/pull/3704) * Gateway: minimize downstream request size [#3737](https://github.com/apollographql/apollo-server/pull/3737) +* experimental: Allow configuration of the query plan store by introducing an `experimental_approximateQueryPlanStoreMiB` property to the `ApolloGateway` constructor options which overrides the default cache size of 30MiB. [#3755](https://github.com/apollographql/apollo-server/pull/3755) # v0.11.6 diff --git a/packages/apollo-gateway/src/index.ts b/packages/apollo-gateway/src/index.ts index a33a4ee7259..03aba950b42 100644 --- a/packages/apollo-gateway/src/index.ts +++ b/packages/apollo-gateway/src/index.ts @@ -58,6 +58,7 @@ interface GatewayConfigBase { experimental_updateServiceDefinitions?: Experimental_UpdateServiceDefinitions; experimental_didUpdateComposition?: Experimental_DidUpdateCompositionCallback; experimental_pollInterval?: number; + experimental_approximateQueryPlanStoreMiB?: number; } interface RemoteGatewayConfig extends GatewayConfigBase { @@ -178,6 +179,8 @@ export class ApolloGateway implements GraphQLService { // how often service defs should be loaded/updated (in ms) protected experimental_pollInterval?: number; + private experimental_approximateQueryPlanStoreMiB?: number; + constructor(config?: GatewayConfig) { this.config = { // TODO: expose the query plan in a more flexible JSON format in the future @@ -219,6 +222,9 @@ export class ApolloGateway implements GraphQLService { this.experimental_didUpdateComposition = config.experimental_didUpdateComposition; + this.experimental_approximateQueryPlanStoreMiB = + config.experimental_approximateQueryPlanStoreMiB; + if ( isManagedConfig(config) && config.experimental_pollInterval && @@ -609,7 +615,9 @@ export class ApolloGateway implements GraphQLService { // only using JSON.stringify on the DocumentNode (and thus doesn't account // for unicode characters, etc.), but it should do a reasonable job at // providing a caching document store for most operations. - maxSize: Math.pow(2, 20) * 30, + maxSize: + Math.pow(2, 20) * + (this.experimental_approximateQueryPlanStoreMiB || 30), sizeCalculator: approximateObjectSize, }); } diff --git a/packages/apollo-server-core/src/ApolloServer.ts b/packages/apollo-server-core/src/ApolloServer.ts index 9da7462c125..61ad86b743a 100644 --- a/packages/apollo-server-core/src/ApolloServer.ts +++ b/packages/apollo-server-core/src/ApolloServer.ts @@ -153,6 +153,8 @@ export class ApolloServerBase { /** @deprecated: This is undefined for servers operating as gateways, and will be removed in a future release **/ protected schema?: GraphQLSchema; private toDispose = new Set<() => void>(); + private experimental_approximateDocumentStoreMiB: + Config['experimental_approximateDocumentStoreMiB']; // The constructor should be universal across all environments. All environment specific behavior should be set by adding or overriding methods constructor(config: Config) { @@ -176,6 +178,7 @@ export class ApolloServerBase { playground, plugins, gateway, + experimental_approximateDocumentStoreMiB, ...requestOptions } = config; @@ -716,7 +719,9 @@ export class ApolloServerBase { // only using JSON.stringify on the DocumentNode (and thus doesn't account // for unicode characters, etc.), but it should do a reasonable job at // providing a caching document store for most operations. - maxSize: Math.pow(2, 20) * 30, + maxSize: + Math.pow(2, 20) * + (this.experimental_approximateDocumentStoreMiB || 30), sizeCalculator: approximateObjectSize, }); } diff --git a/packages/apollo-server-core/src/types.ts b/packages/apollo-server-core/src/types.ts index fe3778b6faf..6eeb844a07f 100644 --- a/packages/apollo-server-core/src/types.ts +++ b/packages/apollo-server-core/src/types.ts @@ -112,6 +112,7 @@ export interface Config extends BaseConfig { uploads?: boolean | FileUploadOptions; playground?: PlaygroundConfig; gateway?: GraphQLService; + experimental_approximateDocumentStoreMiB?: number; } export interface FileUploadOptions {