diff --git a/.api-reports/api-report-core.md b/.api-reports/api-report-core.md index 4a8dfc429e8..3e691e065d6 100644 --- a/.api-reports/api-report-core.md +++ b/.api-reports/api-report-core.md @@ -1739,7 +1739,9 @@ class QueryManager { // (undocumented) getQueryStore(): Record; // (undocumented) - protected inFlightLinkObservables: Map>>; + protected inFlightLinkObservables: Trie<{ + observable?: Observable> | undefined; + }>; // (undocumented) link: ApolloLink; // (undocumented) @@ -2201,9 +2203,9 @@ interface WriteContext extends ReadMergeModifyContext { // src/cache/inmemory/types.ts:126:3 - (ae-forgotten-export) The symbol "KeyFieldsFunction" needs to be exported by the entry point index.d.ts // src/core/ObservableQuery.ts:113:5 - (ae-forgotten-export) The symbol "QueryManager" needs to be exported by the entry point index.d.ts // src/core/ObservableQuery.ts:114:5 - (ae-forgotten-export) The symbol "QueryInfo" needs to be exported by the entry point index.d.ts -// src/core/QueryManager.ts:119:5 - (ae-forgotten-export) The symbol "MutationStoreValue" needs to be exported by the entry point index.d.ts -// src/core/QueryManager.ts:153:5 - (ae-forgotten-export) The symbol "LocalState" needs to be exported by the entry point index.d.ts -// src/core/QueryManager.ts:384:7 - (ae-forgotten-export) The symbol "UpdateQueries" needs to be exported by the entry point index.d.ts +// src/core/QueryManager.ts:120:5 - (ae-forgotten-export) The symbol "MutationStoreValue" needs to be exported by the entry point index.d.ts +// src/core/QueryManager.ts:154:5 - (ae-forgotten-export) The symbol "LocalState" needs to be exported by the entry point index.d.ts +// src/core/QueryManager.ts:394:7 - (ae-forgotten-export) The symbol "UpdateQueries" needs to be exported by the entry point index.d.ts // src/core/watchQueryOptions.ts:191:3 - (ae-forgotten-export) The symbol "UpdateQueryFn" needs to be exported by the entry point index.d.ts // src/link/http/selectHttpOptionsAndBody.ts:128:32 - (ae-forgotten-export) The symbol "HttpQueryOptions" needs to be exported by the entry point index.d.ts diff --git a/.api-reports/api-report-react.md b/.api-reports/api-report-react.md index 65a4bbe7d1f..0b90201df27 100644 --- a/.api-reports/api-report-react.md +++ b/.api-reports/api-report-react.md @@ -16,6 +16,7 @@ import type { Observer } from 'zen-observable-ts'; import type * as ReactTypes from 'react'; import type { Subscriber } from 'zen-observable-ts'; import type { Subscription } from 'zen-observable-ts'; +import { Trie } from '@wry/trie'; import { TypedDocumentNode } from '@graphql-typed-document-node/core'; import type { VariableDefinitionNode } from 'graphql'; @@ -1601,7 +1602,9 @@ class QueryManager { // (undocumented) getQueryStore(): Record; // (undocumented) - protected inFlightLinkObservables: Map>>; + protected inFlightLinkObservables: Trie<{ + observable?: Observable> | undefined; + }>; // (undocumented) link: ApolloLink; // (undocumented) @@ -2286,9 +2289,9 @@ interface WatchQueryOptions { // (undocumented) getQueryStore(): Record; // (undocumented) - protected inFlightLinkObservables: Map>>; + protected inFlightLinkObservables: Trie<{ + observable?: Observable> | undefined; + }>; // (undocumented) link: ApolloLink; // (undocumented) @@ -1745,9 +1748,9 @@ interface WatchQueryOptions { // (undocumented) getQueryStore(): Record; // (undocumented) - protected inFlightLinkObservables: Map>>; + protected inFlightLinkObservables: Trie<{ + observable?: Observable> | undefined; + }>; // (undocumented) link: ApolloLink; // (undocumented) @@ -1641,9 +1644,9 @@ interface WatchQueryOptions { // (undocumented) getQueryStore(): Record; // (undocumented) - protected inFlightLinkObservables: Map>>; + protected inFlightLinkObservables: Trie<{ + observable?: Observable> | undefined; + }>; // (undocumented) link: ApolloLink; // (undocumented) @@ -1686,9 +1689,9 @@ export function withSubscription { // (undocumented) getQueryStore(): Record; // (undocumented) - protected inFlightLinkObservables: Map>>; + protected inFlightLinkObservables: Trie<{ + observable?: Observable> | undefined; + }>; // (undocumented) link: ApolloLink; // (undocumented) @@ -2178,9 +2181,9 @@ interface WatchQueryOptions { // (undocumented) getQueryStore(): Record; // (undocumented) - protected inFlightLinkObservables: Map>>; + protected inFlightLinkObservables: Trie<{ + observable?: Observable> | undefined; + }>; // (undocumented) link: ApolloLink; // (undocumented) @@ -1627,9 +1630,9 @@ interface WatchQueryOptions { // (undocumented) getQueryStore(): Record; // (undocumented) - protected inFlightLinkObservables: Map>>; + protected inFlightLinkObservables: Trie<{ + observable?: Observable> | undefined; + }>; // (undocumented) link: ApolloLink; // (undocumented) @@ -1690,9 +1693,9 @@ export function withWarningSpy(it: (...args: TArgs // src/core/LocalState.ts:46:5 - (ae-forgotten-export) The symbol "FragmentMap" needs to be exported by the entry point index.d.ts // src/core/ObservableQuery.ts:113:5 - (ae-forgotten-export) The symbol "QueryManager" needs to be exported by the entry point index.d.ts // src/core/ObservableQuery.ts:114:5 - (ae-forgotten-export) The symbol "QueryInfo" needs to be exported by the entry point index.d.ts -// src/core/QueryManager.ts:119:5 - (ae-forgotten-export) The symbol "MutationStoreValue" needs to be exported by the entry point index.d.ts -// src/core/QueryManager.ts:153:5 - (ae-forgotten-export) The symbol "LocalState" needs to be exported by the entry point index.d.ts -// src/core/QueryManager.ts:384:7 - (ae-forgotten-export) The symbol "UpdateQueries" needs to be exported by the entry point index.d.ts +// src/core/QueryManager.ts:120:5 - (ae-forgotten-export) The symbol "MutationStoreValue" needs to be exported by the entry point index.d.ts +// src/core/QueryManager.ts:154:5 - (ae-forgotten-export) The symbol "LocalState" needs to be exported by the entry point index.d.ts +// src/core/QueryManager.ts:394:7 - (ae-forgotten-export) The symbol "UpdateQueries" needs to be exported by the entry point index.d.ts // src/core/types.ts:158:3 - (ae-forgotten-export) The symbol "ApolloError" needs to be exported by the entry point index.d.ts // src/core/types.ts:160:3 - (ae-forgotten-export) The symbol "NetworkStatus" needs to be exported by the entry point index.d.ts // src/core/types.ts:178:3 - (ae-forgotten-export) The symbol "MutationQueryReducer" needs to be exported by the entry point index.d.ts diff --git a/.api-reports/api-report-testing_core.md b/.api-reports/api-report-testing_core.md index 313f20a2f54..0cadba43966 100644 --- a/.api-reports/api-report-testing_core.md +++ b/.api-reports/api-report-testing_core.md @@ -15,6 +15,7 @@ import { Observable } from 'zen-observable-ts'; import type { Observer } from 'zen-observable-ts'; import type { Subscriber } from 'zen-observable-ts'; import type { Subscription } from 'zen-observable-ts'; +import { Trie } from '@wry/trie'; import { TypedDocumentNode } from '@graphql-typed-document-node/core'; // Warning: (ae-forgotten-export) The symbol "Modifier" needs to be exported by the entry point index.d.ts @@ -1294,7 +1295,9 @@ class QueryManager { // (undocumented) getQueryStore(): Record; // (undocumented) - protected inFlightLinkObservables: Map>>; + protected inFlightLinkObservables: Trie<{ + observable?: Observable> | undefined; + }>; // (undocumented) link: ApolloLink; // (undocumented) @@ -1646,9 +1649,9 @@ export function withWarningSpy(it: (...args: TArgs // src/core/LocalState.ts:46:5 - (ae-forgotten-export) The symbol "FragmentMap" needs to be exported by the entry point index.d.ts // src/core/ObservableQuery.ts:113:5 - (ae-forgotten-export) The symbol "QueryManager" needs to be exported by the entry point index.d.ts // src/core/ObservableQuery.ts:114:5 - (ae-forgotten-export) The symbol "QueryInfo" needs to be exported by the entry point index.d.ts -// src/core/QueryManager.ts:119:5 - (ae-forgotten-export) The symbol "MutationStoreValue" needs to be exported by the entry point index.d.ts -// src/core/QueryManager.ts:153:5 - (ae-forgotten-export) The symbol "LocalState" needs to be exported by the entry point index.d.ts -// src/core/QueryManager.ts:384:7 - (ae-forgotten-export) The symbol "UpdateQueries" needs to be exported by the entry point index.d.ts +// src/core/QueryManager.ts:120:5 - (ae-forgotten-export) The symbol "MutationStoreValue" needs to be exported by the entry point index.d.ts +// src/core/QueryManager.ts:154:5 - (ae-forgotten-export) The symbol "LocalState" needs to be exported by the entry point index.d.ts +// src/core/QueryManager.ts:394:7 - (ae-forgotten-export) The symbol "UpdateQueries" needs to be exported by the entry point index.d.ts // src/core/types.ts:158:3 - (ae-forgotten-export) The symbol "ApolloError" needs to be exported by the entry point index.d.ts // src/core/types.ts:160:3 - (ae-forgotten-export) The symbol "NetworkStatus" needs to be exported by the entry point index.d.ts // src/core/types.ts:178:3 - (ae-forgotten-export) The symbol "MutationQueryReducer" needs to be exported by the entry point index.d.ts diff --git a/.api-reports/api-report-utilities.md b/.api-reports/api-report-utilities.md index 3ca8456512a..59c8e4d8380 100644 --- a/.api-reports/api-report-utilities.md +++ b/.api-reports/api-report-utilities.md @@ -2018,7 +2018,9 @@ class QueryManager { // (undocumented) getQueryStore(): Record; // (undocumented) - protected inFlightLinkObservables: Map>>; + protected inFlightLinkObservables: Trie<{ + observable?: Observable> | undefined; + }>; // (undocumented) link: ApolloLink; // (undocumented) @@ -2539,9 +2541,9 @@ interface WriteContext extends ReadMergeModifyContext { // src/core/LocalState.ts:71:3 - (ae-forgotten-export) The symbol "ApolloClient" needs to be exported by the entry point index.d.ts // src/core/ObservableQuery.ts:113:5 - (ae-forgotten-export) The symbol "QueryManager" needs to be exported by the entry point index.d.ts // src/core/ObservableQuery.ts:114:5 - (ae-forgotten-export) The symbol "QueryInfo" needs to be exported by the entry point index.d.ts -// src/core/QueryManager.ts:119:5 - (ae-forgotten-export) The symbol "MutationStoreValue" needs to be exported by the entry point index.d.ts -// src/core/QueryManager.ts:153:5 - (ae-forgotten-export) The symbol "LocalState" needs to be exported by the entry point index.d.ts -// src/core/QueryManager.ts:384:7 - (ae-forgotten-export) The symbol "UpdateQueries" needs to be exported by the entry point index.d.ts +// src/core/QueryManager.ts:120:5 - (ae-forgotten-export) The symbol "MutationStoreValue" needs to be exported by the entry point index.d.ts +// src/core/QueryManager.ts:154:5 - (ae-forgotten-export) The symbol "LocalState" needs to be exported by the entry point index.d.ts +// src/core/QueryManager.ts:394:7 - (ae-forgotten-export) The symbol "UpdateQueries" needs to be exported by the entry point index.d.ts // src/core/types.ts:158:3 - (ae-forgotten-export) The symbol "ApolloError" needs to be exported by the entry point index.d.ts // src/core/types.ts:160:3 - (ae-forgotten-export) The symbol "NetworkStatus" needs to be exported by the entry point index.d.ts // src/core/types.ts:178:3 - (ae-forgotten-export) The symbol "MutationQueryReducer" needs to be exported by the entry point index.d.ts diff --git a/.api-reports/api-report.md b/.api-reports/api-report.md index 9e336a0c50a..04a979da240 100644 --- a/.api-reports/api-report.md +++ b/.api-reports/api-report.md @@ -2156,7 +2156,9 @@ class QueryManager { // (undocumented) getQueryStore(): Record; // (undocumented) - protected inFlightLinkObservables: Map>>; + protected inFlightLinkObservables: Trie<{ + observable?: Observable> | undefined; + }>; // (undocumented) link: ApolloLink; // (undocumented) @@ -2958,9 +2960,9 @@ interface WriteContext extends ReadMergeModifyContext { // src/cache/inmemory/types.ts:126:3 - (ae-forgotten-export) The symbol "KeyFieldsFunction" needs to be exported by the entry point index.d.ts // src/core/ObservableQuery.ts:113:5 - (ae-forgotten-export) The symbol "QueryManager" needs to be exported by the entry point index.d.ts // src/core/ObservableQuery.ts:114:5 - (ae-forgotten-export) The symbol "QueryInfo" needs to be exported by the entry point index.d.ts -// src/core/QueryManager.ts:119:5 - (ae-forgotten-export) The symbol "MutationStoreValue" needs to be exported by the entry point index.d.ts -// src/core/QueryManager.ts:153:5 - (ae-forgotten-export) The symbol "LocalState" needs to be exported by the entry point index.d.ts -// src/core/QueryManager.ts:384:7 - (ae-forgotten-export) The symbol "UpdateQueries" needs to be exported by the entry point index.d.ts +// src/core/QueryManager.ts:120:5 - (ae-forgotten-export) The symbol "MutationStoreValue" needs to be exported by the entry point index.d.ts +// src/core/QueryManager.ts:154:5 - (ae-forgotten-export) The symbol "LocalState" needs to be exported by the entry point index.d.ts +// src/core/QueryManager.ts:394:7 - (ae-forgotten-export) The symbol "UpdateQueries" needs to be exported by the entry point index.d.ts // src/core/watchQueryOptions.ts:191:3 - (ae-forgotten-export) The symbol "UpdateQueryFn" needs to be exported by the entry point index.d.ts // src/link/http/selectHttpOptionsAndBody.ts:128:32 - (ae-forgotten-export) The symbol "HttpQueryOptions" needs to be exported by the entry point index.d.ts // src/react/hooks/useBackgroundQuery.ts:26:3 - (ae-forgotten-export) The symbol "FetchMoreFunction" needs to be exported by the entry point index.d.ts diff --git a/.changeset/sixty-boxes-rest.md b/.changeset/sixty-boxes-rest.md new file mode 100644 index 00000000000..cce6eb7a98a --- /dev/null +++ b/.changeset/sixty-boxes-rest.md @@ -0,0 +1,8 @@ +--- +"@apollo/client": minor +--- + +`QueryManager.inFlightLinkObservables` now uses a strong `Trie` as an internal data structure. + +#### Warning: requires `@apollo/experimental-nextjs-app-support` update +If you are using `@apollo/experimental-nextjs-app-support`, you will need to update that to at least 0.5.2, as it accesses this internal data structure. diff --git a/.size-limits.json b/.size-limits.json index e196670f752..dfe8306d94f 100644 --- a/.size-limits.json +++ b/.size-limits.json @@ -1,4 +1,4 @@ { - "dist/apollo-client.min.cjs": 38632, - "import { ApolloClient, InMemoryCache, HttpLink } from \"dist/index.js\" (production)": 32215 + "dist/apollo-client.min.cjs": 38693, + "import { ApolloClient, InMemoryCache, HttpLink } from \"dist/index.js\" (production)": 32306 } diff --git a/src/core/QueryManager.ts b/src/core/QueryManager.ts index f6c471ef840..3a94078f3da 100644 --- a/src/core/QueryManager.ts +++ b/src/core/QueryManager.ts @@ -99,6 +99,7 @@ interface TransformCacheEntry { } import type { DefaultOptions } from "./ApolloClient.js"; +import { Trie } from "@wry/trie"; export class QueryManager { public cache: ApolloCache; @@ -182,6 +183,15 @@ export class QueryManager { if ((this.onBroadcast = onBroadcast)) { this.mutationStore = Object.create(null); } + + // TODO: remove before we release 3.9 + Object.defineProperty(this.inFlightLinkObservables, "get", { + value: () => { + throw new Error( + "This version of Apollo Client requires at least @apollo/experimental-nextjs-app-support version 0.5.2." + ); + }, + }); } /** @@ -1065,10 +1075,9 @@ export class QueryManager { // Use protected instead of private field so // @apollo/experimental-nextjs-app-support can access type info. - protected inFlightLinkObservables = new Map< - string, - Map> - >(); + protected inFlightLinkObservables = new Trie<{ + observable?: Observable>; + }>(false); private getObservableFromLink( query: DocumentNode, @@ -1078,7 +1087,7 @@ export class QueryManager { deduplication: boolean = context?.queryDeduplication ?? this.queryDeduplication ): Observable> { - let observable: Observable>; + let observable: Observable> | undefined; const { serverQuery, clientQuery } = this.getDocumentInfo(query); if (serverQuery) { @@ -1098,24 +1107,22 @@ export class QueryManager { if (deduplication) { const printedServerQuery = print(serverQuery); - const byVariables = - inFlightLinkObservables.get(printedServerQuery) || new Map(); - inFlightLinkObservables.set(printedServerQuery, byVariables); - const varJson = canonicalStringify(variables); - observable = byVariables.get(varJson); + const entry = inFlightLinkObservables.lookup( + printedServerQuery, + varJson + ); + + observable = entry.observable; if (!observable) { const concast = new Concast([ execute(link, operation) as Observable>, ]); - - byVariables.set(varJson, (observable = concast)); + observable = entry.observable = concast; concast.beforeNext(() => { - if (byVariables.delete(varJson) && byVariables.size < 1) { - inFlightLinkObservables.delete(printedServerQuery); - } + inFlightLinkObservables.remove(printedServerQuery, varJson); }); } } else { diff --git a/src/core/__tests__/QueryManager/index.ts b/src/core/__tests__/QueryManager/index.ts index 6358d171f4c..8a911fd72de 100644 --- a/src/core/__tests__/QueryManager/index.ts +++ b/src/core/__tests__/QueryManager/index.ts @@ -47,6 +47,7 @@ import observableToPromise, { import { itAsync, subscribeAndCount } from "../../../testing/core"; import { ApolloClient } from "../../../core"; import { mockFetchQuery } from "../ObservableQuery"; +import { Concast, print } from "../../../utilities"; interface MockedMutation { reject: (reason: any) => any; @@ -6016,7 +6017,11 @@ describe("QueryManager", () => { queryManager.query({ query, context: { queryDeduplication: true } }); - expect(queryManager["inFlightLinkObservables"].size).toBe(1); + expect( + queryManager["inFlightLinkObservables"].peek(print(query), "{}") + ).toEqual({ + observable: expect.any(Concast), + }); }); it("should allow overriding global queryDeduplication: true to false", () => { @@ -6042,7 +6047,9 @@ describe("QueryManager", () => { queryManager.query({ query, context: { queryDeduplication: false } }); - expect(queryManager["inFlightLinkObservables"].size).toBe(0); + expect( + queryManager["inFlightLinkObservables"].peek(print(query), "{}") + ).toBeUndefined(); }); });