From 139acd1153afa1445b69dcb4e139668ab8c5889a Mon Sep 17 00:00:00 2001 From: Lenz Weber-Tronic Date: Fri, 1 Dec 2023 15:20:20 +0100 Subject: [PATCH] `documentTransform`: use `optimism` and `WeakCache` (#11389) --- .api-reports/api-report-core.md | 5 -- .api-reports/api-report-react.md | 8 +-- .api-reports/api-report-react_components.md | 8 +-- .api-reports/api-report-react_context.md | 8 +-- .api-reports/api-report-react_hoc.md | 8 +-- .api-reports/api-report-react_hooks.md | 8 +-- .api-reports/api-report-react_ssr.md | 8 +-- .api-reports/api-report-testing.md | 8 +-- .api-reports/api-report-testing_core.md | 8 +-- .api-reports/api-report-utilities.md | 5 -- .api-reports/api-report.md | 5 -- .changeset/dirty-kids-crash.md | 5 ++ .size-limits.json | 4 +- src/utilities/graphql/DocumentTransform.ts | 65 ++++++++++----------- 14 files changed, 54 insertions(+), 99 deletions(-) create mode 100644 .changeset/dirty-kids-crash.md diff --git a/.api-reports/api-report-core.md b/.api-reports/api-report-core.md index ecbbbe9959d..8129823a675 100644 --- a/.api-reports/api-report-core.md +++ b/.api-reports/api-report-core.md @@ -558,11 +558,6 @@ export class DocumentTransform { // (undocumented) concat(otherTransform: DocumentTransform): DocumentTransform; // (undocumented) - getStableCacheEntry(document: DocumentNode): { - key: DocumentTransformCacheKey; - value?: DocumentNode | undefined; - } | undefined; - // (undocumented) static identity(): DocumentTransform; resetCache(): void; // (undocumented) diff --git a/.api-reports/api-report-react.md b/.api-reports/api-report-react.md index 00e6b5ea122..16a48677e3e 100644 --- a/.api-reports/api-report-react.md +++ b/.api-reports/api-report-react.md @@ -677,11 +677,6 @@ class DocumentTransform { // (undocumented) concat(otherTransform: DocumentTransform): DocumentTransform; // (undocumented) - getStableCacheEntry(document: DocumentNode): { - key: DocumentTransformCacheKey; - value?: DocumentNode | undefined; - } | undefined; - // (undocumented) static identity(): DocumentTransform; resetCache(): void; // (undocumented) @@ -697,6 +692,8 @@ type DocumentTransformCacheKey = ReadonlyArray; interface DocumentTransformOptions { // (undocumented) cache?: boolean; + // Warning: (ae-forgotten-export) The symbol "DocumentTransformCacheKey" needs to be exported by the entry point index.d.ts + // // (undocumented) getCacheKey?: (document: DocumentNode) => DocumentTransformCacheKey | undefined; } @@ -2224,7 +2221,6 @@ interface WatchQueryOptions; interface DocumentTransformOptions { // (undocumented) cache?: boolean; + // Warning: (ae-forgotten-export) The symbol "DocumentTransformCacheKey" needs to be exported by the entry point index.d.ts + // // (undocumented) getCacheKey?: (document: DocumentNode) => DocumentTransformCacheKey | undefined; } @@ -1689,7 +1686,6 @@ interface WatchQueryOptions; interface DocumentTransformOptions { // (undocumented) cache?: boolean; + // Warning: (ae-forgotten-export) The symbol "DocumentTransformCacheKey" needs to be exported by the entry point index.d.ts + // // (undocumented) getCacheKey?: (document: DocumentNode) => DocumentTransformCacheKey | undefined; } @@ -1585,7 +1582,6 @@ interface WatchQueryOptions; interface DocumentTransformOptions { // (undocumented) cache?: boolean; + // Warning: (ae-forgotten-export) The symbol "DocumentTransformCacheKey" needs to be exported by the entry point index.d.ts + // // (undocumented) getCacheKey?: (document: DocumentNode) => DocumentTransformCacheKey | undefined; } @@ -1630,7 +1627,6 @@ export function withSubscription; interface DocumentTransformOptions { // (undocumented) cache?: boolean; + // Warning: (ae-forgotten-export) The symbol "DocumentTransformCacheKey" needs to be exported by the entry point index.d.ts + // // (undocumented) getCacheKey?: (document: DocumentNode) => DocumentTransformCacheKey | undefined; } @@ -2115,7 +2112,6 @@ interface WatchQueryOptions; interface DocumentTransformOptions { // (undocumented) cache?: boolean; + // Warning: (ae-forgotten-export) The symbol "DocumentTransformCacheKey" needs to be exported by the entry point index.d.ts + // // (undocumented) getCacheKey?: (document: DocumentNode) => DocumentTransformCacheKey | undefined; } @@ -1571,7 +1568,6 @@ interface WatchQueryOptions; interface DocumentTransformOptions { // (undocumented) cache?: boolean; + // Warning: (ae-forgotten-export) The symbol "DocumentTransformCacheKey" needs to be exported by the entry point index.d.ts + // // (undocumented) getCacheKey?: (document: DocumentNode) => DocumentTransformCacheKey | undefined; } @@ -1633,7 +1630,6 @@ export function withWarningSpy(it: (...args: TArgs // src/core/types.ts:174:3 - (ae-forgotten-export) The symbol "MutationQueryReducer" needs to be exported by the entry point index.d.ts // src/core/types.ts:201:5 - (ae-forgotten-export) The symbol "Resolver" needs to be exported by the entry point index.d.ts // src/core/watchQueryOptions.ts:253:2 - (ae-forgotten-export) The symbol "UpdateQueryFn" needs to be exported by the entry point index.d.ts -// src/utilities/graphql/DocumentTransform.ts:129:7 - (ae-forgotten-export) The symbol "DocumentTransformCacheKey" needs to be exported by the entry point index.d.ts // (No @packageDocumentation comment for this package) diff --git a/.api-reports/api-report-testing_core.md b/.api-reports/api-report-testing_core.md index 54169c324b6..a306aeb99fb 100644 --- a/.api-reports/api-report-testing_core.md +++ b/.api-reports/api-report-testing_core.md @@ -537,11 +537,6 @@ class DocumentTransform { // (undocumented) concat(otherTransform: DocumentTransform): DocumentTransform; // (undocumented) - getStableCacheEntry(document: DocumentNode): { - key: DocumentTransformCacheKey; - value?: DocumentNode | undefined; - } | undefined; - // (undocumented) static identity(): DocumentTransform; resetCache(): void; // (undocumented) @@ -557,6 +552,8 @@ type DocumentTransformCacheKey = ReadonlyArray; interface DocumentTransformOptions { // (undocumented) cache?: boolean; + // Warning: (ae-forgotten-export) The symbol "DocumentTransformCacheKey" needs to be exported by the entry point index.d.ts + // // (undocumented) getCacheKey?: (document: DocumentNode) => DocumentTransformCacheKey | undefined; } @@ -1590,7 +1587,6 @@ export function withWarningSpy(it: (...args: TArgs // src/core/types.ts:174:3 - (ae-forgotten-export) The symbol "MutationQueryReducer" needs to be exported by the entry point index.d.ts // src/core/types.ts:201:5 - (ae-forgotten-export) The symbol "Resolver" needs to be exported by the entry point index.d.ts // src/core/watchQueryOptions.ts:253:2 - (ae-forgotten-export) The symbol "UpdateQueryFn" needs to be exported by the entry point index.d.ts -// src/utilities/graphql/DocumentTransform.ts:129:7 - (ae-forgotten-export) The symbol "DocumentTransformCacheKey" needs to be exported by the entry point index.d.ts // (No @packageDocumentation comment for this package) diff --git a/.api-reports/api-report-utilities.md b/.api-reports/api-report-utilities.md index 0f3236d629d..ac31c32b9d2 100644 --- a/.api-reports/api-report-utilities.md +++ b/.api-reports/api-report-utilities.md @@ -715,11 +715,6 @@ export class DocumentTransform { // (undocumented) concat(otherTransform: DocumentTransform): DocumentTransform; // (undocumented) - getStableCacheEntry(document: DocumentNode): { - key: DocumentTransformCacheKey; - value?: DocumentNode | undefined; - } | undefined; - // (undocumented) static identity(): DocumentTransform; resetCache(): void; // (undocumented) diff --git a/.api-reports/api-report.md b/.api-reports/api-report.md index baf0f36ed45..d6b96223bdf 100644 --- a/.api-reports/api-report.md +++ b/.api-reports/api-report.md @@ -701,11 +701,6 @@ export class DocumentTransform { // (undocumented) concat(otherTransform: DocumentTransform): DocumentTransform; // (undocumented) - getStableCacheEntry(document: DocumentNode): { - key: DocumentTransformCacheKey; - value?: DocumentNode | undefined; - } | undefined; - // (undocumented) static identity(): DocumentTransform; resetCache(): void; // (undocumented) diff --git a/.changeset/dirty-kids-crash.md b/.changeset/dirty-kids-crash.md new file mode 100644 index 00000000000..504c049268d --- /dev/null +++ b/.changeset/dirty-kids-crash.md @@ -0,0 +1,5 @@ +--- +"@apollo/client": patch +--- + +`documentTransform`: use `optimism` and `WeakCache` instead of directly storing data on the `Trie` diff --git a/.size-limits.json b/.size-limits.json index 9d19488680a..6f8c966652b 100644 --- a/.size-limits.json +++ b/.size-limits.json @@ -1,4 +1,4 @@ { - "dist/apollo-client.min.cjs": 38646, - "import { ApolloClient, InMemoryCache, HttpLink } from \"dist/index.js\" (production)": 32304 + "dist/apollo-client.min.cjs": 38632, + "import { ApolloClient, InMemoryCache, HttpLink } from \"dist/index.js\" (production)": 32319 } diff --git a/src/utilities/graphql/DocumentTransform.ts b/src/utilities/graphql/DocumentTransform.ts index d3b4870f390..7a5ce40fe4c 100644 --- a/src/utilities/graphql/DocumentTransform.ts +++ b/src/utilities/graphql/DocumentTransform.ts @@ -3,6 +3,8 @@ import { canUseWeakMap, canUseWeakSet } from "../common/canUse.js"; import { checkDocument } from "./getFromAST.js"; import { invariant } from "../globals/index.js"; import type { DocumentNode } from "graphql"; +import { WeakCache } from "@wry/caches"; +import { wrap } from "optimism"; export type DocumentTransformCacheKey = ReadonlyArray; @@ -21,14 +23,11 @@ function identity(document: DocumentNode) { export class DocumentTransform { private readonly transform: TransformFn; + private cached: boolean; private readonly resultCache = canUseWeakSet ? new WeakSet() : new Set(); - private stableCacheKeys: - | Trie<{ key: DocumentTransformCacheKey; value?: DocumentNode }> - | undefined; - // This default implementation of getCacheKey can be overridden by providing // options.getCacheKey to the DocumentTransform constructor. In general, a // getCacheKey function may either return an array of keys (often including @@ -73,18 +72,40 @@ export class DocumentTransform { // Override default `getCacheKey` function, which returns [document]. this.getCacheKey = options.getCacheKey; } + this.cached = options.cache !== false; - if (options.cache !== false) { - this.stableCacheKeys = new Trie(canUseWeakMap, (key) => ({ key })); - } + this.resetCache(); } /** * Resets the internal cache of this transform, if it has one. */ resetCache() { - this.stableCacheKeys = - this.stableCacheKeys && new Trie(canUseWeakMap, (key) => ({ key })); + if (this.cached) { + const stableCacheKeys = new Trie(canUseWeakMap); + this.performWork = wrap( + DocumentTransform.prototype.performWork.bind(this), + { + makeCacheKey: (document) => { + const cacheKeys = this.getCacheKey(document); + if (cacheKeys) { + invariant( + Array.isArray(cacheKeys), + "`getCacheKey` must return an array or undefined" + ); + return stableCacheKeys.lookupArray(cacheKeys); + } + }, + max: 1000 /** TODO: decide on a maximum size (will do all max sizes in a combined separate PR) */, + cache: WeakCache, + } + ); + } + } + + private performWork(document: DocumentNode) { + checkDocument(document); + return this.transform(document); } transformDocument(document: DocumentNode) { @@ -94,22 +115,10 @@ export class DocumentTransform { return document; } - const cacheEntry = this.getStableCacheEntry(document); - - if (cacheEntry && cacheEntry.value) { - return cacheEntry.value; - } - - checkDocument(document); - - const transformedDocument = this.transform(document); + const transformedDocument = this.performWork(document); this.resultCache.add(transformedDocument); - if (cacheEntry) { - cacheEntry.value = transformedDocument; - } - return transformedDocument; } @@ -124,16 +133,4 @@ export class DocumentTransform { { cache: false } ); } - - getStableCacheEntry(document: DocumentNode) { - if (!this.stableCacheKeys) return; - const cacheKeys = this.getCacheKey(document); - if (cacheKeys) { - invariant( - Array.isArray(cacheKeys), - "`getCacheKey` must return an array or undefined" - ); - return this.stableCacheKeys.lookupArray(cacheKeys); - } - } }