Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

useBackgroundQuery: remove promiseCache, work around race condition #11366

Merged
merged 27 commits into from
Dec 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
8ecd36f
`useSuspenseQuery`: remove `promiseCache`
phryneas Nov 15, 2023
b8c51af
missed cleanup
phryneas Nov 15, 2023
79577b5
WIP status: useBackgroundQuery
phryneas Nov 15, 2023
1510019
working reimplementation
phryneas Nov 16, 2023
532505a
update `current[0]` correctly
phryneas Nov 16, 2023
50c2149
change `key` to empty object
phryneas Nov 16, 2023
6dd943a
Merge branch 'pr/remove-useSuspenseQuery-promiseCache' into pr/remove…
phryneas Nov 16, 2023
c9c3177
move `secondIfNewerFulfilledOrFirst` call into `unwrapQueryRef`
phryneas Nov 21, 2023
4a5c3e2
remove unused import
phryneas Nov 21, 2023
083af14
PR feedback
phryneas Nov 30, 2023
3da56f0
more PR feedback
phryneas Nov 30, 2023
2cad580
review feedback
phryneas Nov 30, 2023
346e5e8
re-add delay to test
phryneas Nov 30, 2023
fc66f12
add more mock delays
phryneas Nov 30, 2023
1e3297e
Separate withSequence from createFulfilledPromise and createRejectedP…
jerelmiller Nov 30, 2023
a6e421a
Remove need for sequencing on promises by returning newer promise whe…
jerelmiller Dec 1, 2023
53871a1
Merge remote-tracking branch 'origin/release-3.9' into pr/remove-useB…
phryneas Dec 1, 2023
82bd4ae
`useLoadableQuery`: remove `promiseCache`
phryneas Dec 1, 2023
f8e0e05
remove second argument to `wrapQueryRef`
phryneas Dec 1, 2023
10175b5
chores
phryneas Dec 1, 2023
b248d6c
Merge remote-tracking branch 'origin/release-3.9' into pr/remove-useB…
phryneas Dec 1, 2023
4a413c3
fix most tests by adding delays
phryneas Dec 1, 2023
8010b0c
Clean up Prettier, Size-limit, and Api-Extractor
phryneas Dec 1, 2023
c150398
add `skipNonTrackingRenders` to profiler
phryneas Dec 1, 2023
d07aa6a
add comments to "phantom render" tests
phryneas Dec 1, 2023
1eef04f
Merge branch 'release-3.9' into pr/remove-useBackgroundQuery-promiseC…
phryneas Dec 1, 2023
4bde5a0
Clean up Prettier, Size-limit, and Api-Extractor
phryneas Dec 1, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 47 additions & 8 deletions .api-reports/api-report-react.md
Original file line number Diff line number Diff line change
Expand Up @@ -807,6 +807,14 @@ interface FragmentMap {
// @public (undocumented)
type FragmentMatcher = (rootValue: any, typeCondition: string, context: any) => boolean;

// @public (undocumented)
interface FulfilledPromise<TValue> extends Promise<TValue> {
// (undocumented)
status: "fulfilled";
// (undocumented)
value: TValue;
}

// @public (undocumented)
export function getApolloContext(): ReactTypes.Context<ApolloContextValue>;

Expand Down Expand Up @@ -858,7 +866,7 @@ class InternalQueryReference<TData = unknown> {
// Warning: (ae-forgotten-export) The symbol "InternalQueryReferenceOptions" needs to be exported by the entry point index.d.ts
constructor(observable: ObservableQuery<TData>, options: InternalQueryReferenceOptions);
// (undocumented)
applyOptions(watchQueryOptions: ObservedOptions): Promise<ApolloQueryResult<TData>>;
applyOptions(watchQueryOptions: ObservedOptions): QueryRefPromise<TData>;
// Warning: (ae-forgotten-export) The symbol "ObservedOptions" needs to be exported by the entry point index.d.ts
//
// (undocumented)
Expand All @@ -877,10 +885,10 @@ class InternalQueryReference<TData = unknown> {
listen(listener: Listener<TData>): () => void;
// (undocumented)
readonly observable: ObservableQuery<TData>;
// Warning: (ae-forgotten-export) The symbol "QueryRefPromise" needs to be exported by the entry point index.d.ts
//
// (undocumented)
promise: Promise<ApolloQueryResult<TData>>;
// (undocumented)
promiseCache?: Map<QueryKey, Promise<ApolloQueryResult<TData>>>;
promise: QueryRefPromise<TData>;
// (undocumented)
refetch(variables: OperationVariables | undefined): Promise<ApolloQueryResult<TData>>;
// (undocumented)
Expand Down Expand Up @@ -966,7 +974,7 @@ export type LazyQueryResult<TData, TVariables extends OperationVariables> = Quer
export type LazyQueryResultTuple<TData, TVariables extends OperationVariables> = [LazyQueryExecFunction<TData, TVariables>, QueryResult<TData, TVariables>];

// @public (undocumented)
type Listener<TData> = (promise: Promise<ApolloQueryResult<TData>>) => void;
type Listener<TData> = (promise: QueryRefPromise<TData>) => void;

// @public (undocumented)
export type LoadableQueryHookFetchPolicy = Extract<WatchQueryFetchPolicy, "cache-first" | "network-only" | "no-cache" | "cache-and-network">;
Expand Down Expand Up @@ -1363,9 +1371,25 @@ export namespace parser {
// @public (undocumented)
type Path = ReadonlyArray<string | number>;

// @public (undocumented)
interface PendingPromise<TValue> extends Promise<TValue> {
// (undocumented)
status: "pending";
}

// @public (undocumented)
type Primitive = null | undefined | string | number | boolean | symbol | bigint;

// @public (undocumented)
const PROMISE_SYMBOL: unique symbol;

// Warning: (ae-forgotten-export) The symbol "PendingPromise" needs to be exported by the entry point index.d.ts
// Warning: (ae-forgotten-export) The symbol "FulfilledPromise" needs to be exported by the entry point index.d.ts
// Warning: (ae-forgotten-export) The symbol "RejectedPromise" needs to be exported by the entry point index.d.ts
//
// @public (undocumented)
type PromiseWithState<TValue> = PendingPromise<TValue> | FulfilledPromise<TValue> | RejectedPromise<TValue>;

// @public (undocumented)
const QUERY_REFERENCE_SYMBOL: unique symbol;

Expand Down Expand Up @@ -1619,12 +1643,19 @@ interface QueryOptions<TVariables = OperationVariables, TData = any> {
//
// @public
export interface QueryReference<TData = unknown> {
// (undocumented)
[PROMISE_SYMBOL]: QueryRefPromise<TData>;
// Warning: (ae-forgotten-export) The symbol "InternalQueryReference" needs to be exported by the entry point index.d.ts
//
// (undocumented)
[QUERY_REFERENCE_SYMBOL]: InternalQueryReference<TData>;
readonly [QUERY_REFERENCE_SYMBOL]: InternalQueryReference<TData>;
}

// Warning: (ae-forgotten-export) The symbol "PromiseWithState" needs to be exported by the entry point index.d.ts
//
// @public (undocumented)
type QueryRefPromise<TData> = PromiseWithState<ApolloQueryResult<TData>>;

// @public (undocumented)
export interface QueryResult<TData = any, TVariables extends OperationVariables = OperationVariables> extends ObservableQueryFields<TData, TVariables> {
// (undocumented)
Expand Down Expand Up @@ -1738,6 +1769,14 @@ type RefetchQueryDescriptor = string | DocumentNode;
// @public (undocumented)
type RefetchWritePolicy = "merge" | "overwrite";

// @public (undocumented)
interface RejectedPromise<TValue> extends Promise<TValue> {
// (undocumented)
reason: unknown;
// (undocumented)
status: "rejected";
}

// @public (undocumented)
class RenderPromises {
// (undocumented)
Expand Down Expand Up @@ -2218,8 +2257,8 @@ interface WatchQueryOptions<TVariables extends OperationVariables = OperationVar
// 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/react/hooks/useBackgroundQuery.ts:26:3 - (ae-forgotten-export) The symbol "FetchMoreFunction" needs to be exported by the entry point index.d.ts
// src/react/hooks/useBackgroundQuery.ts:27:3 - (ae-forgotten-export) The symbol "RefetchFunction" needs to be exported by the entry point index.d.ts
// src/react/hooks/useBackgroundQuery.ts:30:3 - (ae-forgotten-export) The symbol "FetchMoreFunction" needs to be exported by the entry point index.d.ts
// src/react/hooks/useBackgroundQuery.ts:31:3 - (ae-forgotten-export) The symbol "RefetchFunction" needs to be exported by the entry point index.d.ts
// src/react/hooks/useLoadableQuery.ts:49:5 - (ae-forgotten-export) The symbol "ResetFunction" needs to be exported by the entry point index.d.ts

// (No @packageDocumentation comment for this package)
Expand Down
55 changes: 47 additions & 8 deletions .api-reports/api-report-react_hooks.md
Original file line number Diff line number Diff line change
Expand Up @@ -767,6 +767,14 @@ interface FragmentMap {
// @public (undocumented)
type FragmentMatcher = (rootValue: any, typeCondition: string, context: any) => boolean;

// @public (undocumented)
interface FulfilledPromise<TValue> extends Promise<TValue> {
// (undocumented)
status: "fulfilled";
// (undocumented)
value: TValue;
}

// @public (undocumented)
type GraphQLErrors = ReadonlyArray<GraphQLError>;

Expand Down Expand Up @@ -805,7 +813,7 @@ class InternalQueryReference<TData = unknown> {
// Warning: (ae-forgotten-export) The symbol "InternalQueryReferenceOptions" needs to be exported by the entry point index.d.ts
constructor(observable: ObservableQuery<TData>, options: InternalQueryReferenceOptions);
// (undocumented)
applyOptions(watchQueryOptions: ObservedOptions): Promise<ApolloQueryResult<TData>>;
applyOptions(watchQueryOptions: ObservedOptions): QueryRefPromise<TData>;
// Warning: (ae-forgotten-export) The symbol "ObservedOptions" needs to be exported by the entry point index.d.ts
//
// (undocumented)
Expand All @@ -824,10 +832,10 @@ class InternalQueryReference<TData = unknown> {
listen(listener: Listener<TData>): () => void;
// (undocumented)
readonly observable: ObservableQuery<TData>;
// Warning: (ae-forgotten-export) The symbol "QueryRefPromise" needs to be exported by the entry point index.d.ts
//
// (undocumented)
promise: Promise<ApolloQueryResult<TData>>;
// (undocumented)
promiseCache?: Map<QueryKey, Promise<ApolloQueryResult<TData>>>;
promise: QueryRefPromise<TData>;
// (undocumented)
refetch(variables: OperationVariables | undefined): Promise<ApolloQueryResult<TData>>;
// (undocumented)
Expand Down Expand Up @@ -917,7 +925,7 @@ interface LazyQueryHookOptions<TData = any, TVariables extends OperationVariable
type LazyQueryResultTuple<TData, TVariables extends OperationVariables> = [LazyQueryExecFunction<TData, TVariables>, QueryResult<TData, TVariables>];

// @public (undocumented)
type Listener<TData> = (promise: Promise<ApolloQueryResult<TData>>) => void;
type Listener<TData> = (promise: QueryRefPromise<TData>) => void;

// @public (undocumented)
type LoadableQueryHookFetchPolicy = Extract<WatchQueryFetchPolicy, "cache-first" | "network-only" | "no-cache" | "cache-and-network">;
Expand Down Expand Up @@ -1301,9 +1309,25 @@ type OperationVariables = Record<string, any>;
// @public (undocumented)
type Path = ReadonlyArray<string | number>;

// @public (undocumented)
interface PendingPromise<TValue> extends Promise<TValue> {
// (undocumented)
status: "pending";
}

// @public (undocumented)
type Primitive = null | undefined | string | number | boolean | symbol | bigint;

// @public (undocumented)
const PROMISE_SYMBOL: unique symbol;

// Warning: (ae-forgotten-export) The symbol "PendingPromise" needs to be exported by the entry point index.d.ts
// Warning: (ae-forgotten-export) The symbol "FulfilledPromise" needs to be exported by the entry point index.d.ts
// Warning: (ae-forgotten-export) The symbol "RejectedPromise" needs to be exported by the entry point index.d.ts
//
// @public (undocumented)
type PromiseWithState<TValue> = PendingPromise<TValue> | FulfilledPromise<TValue> | RejectedPromise<TValue>;

// @public (undocumented)
const QUERY_REFERENCE_SYMBOL: unique symbol;

Expand Down Expand Up @@ -1537,12 +1561,19 @@ interface QueryOptions<TVariables = OperationVariables, TData = any> {
//
// @public
interface QueryReference<TData = unknown> {
// (undocumented)
[PROMISE_SYMBOL]: QueryRefPromise<TData>;
// Warning: (ae-forgotten-export) The symbol "InternalQueryReference" needs to be exported by the entry point index.d.ts
//
// (undocumented)
[QUERY_REFERENCE_SYMBOL]: InternalQueryReference<TData>;
readonly [QUERY_REFERENCE_SYMBOL]: InternalQueryReference<TData>;
}

// Warning: (ae-forgotten-export) The symbol "PromiseWithState" needs to be exported by the entry point index.d.ts
//
// @public (undocumented)
type QueryRefPromise<TData> = PromiseWithState<ApolloQueryResult<TData>>;

// Warning: (ae-forgotten-export) The symbol "ObservableQueryFields" needs to be exported by the entry point index.d.ts
//
// @public (undocumented)
Expand Down Expand Up @@ -1652,6 +1683,14 @@ type RefetchQueryDescriptor = string | DocumentNode;
// @public (undocumented)
type RefetchWritePolicy = "merge" | "overwrite";

// @public (undocumented)
interface RejectedPromise<TValue> extends Promise<TValue> {
// (undocumented)
reason: unknown;
// (undocumented)
status: "rejected";
}

// @public (undocumented)
type RequestHandler = (operation: Operation, forward: NextLink) => Observable<FetchResult> | null;

Expand Down Expand Up @@ -2109,8 +2148,8 @@ interface WatchQueryOptions<TVariables extends OperationVariables = OperationVar
// 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/react/hooks/useBackgroundQuery.ts:26:3 - (ae-forgotten-export) The symbol "FetchMoreFunction" needs to be exported by the entry point index.d.ts
// src/react/hooks/useBackgroundQuery.ts:27:3 - (ae-forgotten-export) The symbol "RefetchFunction" needs to be exported by the entry point index.d.ts
// src/react/hooks/useBackgroundQuery.ts:30:3 - (ae-forgotten-export) The symbol "FetchMoreFunction" needs to be exported by the entry point index.d.ts
// src/react/hooks/useBackgroundQuery.ts:31:3 - (ae-forgotten-export) The symbol "RefetchFunction" needs to be exported by the entry point index.d.ts
// src/react/hooks/useLoadableQuery.ts:49:5 - (ae-forgotten-export) The symbol "ResetFunction" needs to be exported by the entry point index.d.ts

// (No @packageDocumentation comment for this package)
Expand Down
4 changes: 1 addition & 3 deletions .api-reports/api-report-utilities.md
Original file line number Diff line number Diff line change
Expand Up @@ -1290,8 +1290,6 @@ export function isQueryOperation(document: DocumentNode): boolean;
// @public (undocumented)
export function isReference(obj: any): obj is Reference;

// Warning: (ae-forgotten-export) The symbol "PromiseWithState" needs to be exported by the entry point index.d.ts
//
// @public (undocumented)
export function isStatefulPromise<TValue>(promise: Promise<TValue>): promise is PromiseWithState<TValue>;

Expand Down Expand Up @@ -1831,7 +1829,7 @@ export { print_2 as print }
// Warning: (ae-forgotten-export) The symbol "PendingPromise" needs to be exported by the entry point index.d.ts
//
// @public (undocumented)
type PromiseWithState<TValue> = PendingPromise<TValue> | FulfilledPromise<TValue> | RejectedPromise<TValue>;
export type PromiseWithState<TValue> = PendingPromise<TValue> | FulfilledPromise<TValue> | RejectedPromise<TValue>;

// @public (undocumented)
class QueryInfo {
Expand Down
55 changes: 47 additions & 8 deletions .api-reports/api-report.md
Original file line number Diff line number Diff line change
Expand Up @@ -1025,6 +1025,14 @@ export function fromError<T>(errorValue: any): Observable<T>;
// @public (undocumented)
export function fromPromise<T>(promise: Promise<T>): Observable<T>;

// @public (undocumented)
interface FulfilledPromise<TValue> extends Promise<TValue> {
// (undocumented)
status: "fulfilled";
// (undocumented)
value: TValue;
}

// @public (undocumented)
export function getApolloContext(): ReactTypes.Context<ApolloContextValue>;

Expand Down Expand Up @@ -1204,7 +1212,7 @@ class InternalQueryReference<TData = unknown> {
// Warning: (ae-forgotten-export) The symbol "InternalQueryReferenceOptions" needs to be exported by the entry point index.d.ts
constructor(observable: ObservableQuery<TData>, options: InternalQueryReferenceOptions);
// (undocumented)
applyOptions(watchQueryOptions: ObservedOptions): Promise<ApolloQueryResult<TData>>;
applyOptions(watchQueryOptions: ObservedOptions): QueryRefPromise<TData>;
// Warning: (ae-forgotten-export) The symbol "ObservedOptions" needs to be exported by the entry point index.d.ts
//
// (undocumented)
Expand All @@ -1223,10 +1231,10 @@ class InternalQueryReference<TData = unknown> {
listen(listener: Listener<TData>): () => void;
// (undocumented)
readonly observable: ObservableQuery<TData>;
// Warning: (ae-forgotten-export) The symbol "QueryRefPromise" needs to be exported by the entry point index.d.ts
//
// (undocumented)
promise: Promise<ApolloQueryResult<TData>>;
// (undocumented)
promiseCache?: Map<QueryKey, Promise<ApolloQueryResult<TData>>>;
promise: QueryRefPromise<TData>;
// (undocumented)
refetch(variables: OperationVariables | undefined): Promise<ApolloQueryResult<TData>>;
// (undocumented)
Expand Down Expand Up @@ -1358,7 +1366,7 @@ export type LazyQueryResult<TData, TVariables extends OperationVariables> = Quer
export type LazyQueryResultTuple<TData, TVariables extends OperationVariables> = [LazyQueryExecFunction<TData, TVariables>, QueryResult<TData, TVariables>];

// @public (undocumented)
type Listener<TData> = (promise: Promise<ApolloQueryResult<TData>>) => void;
type Listener<TData> = (promise: QueryRefPromise<TData>) => void;

// @public (undocumented)
export type LoadableQueryHookFetchPolicy = Extract<WatchQueryFetchPolicy, "cache-first" | "network-only" | "no-cache" | "cache-and-network">;
Expand Down Expand Up @@ -1844,6 +1852,12 @@ export namespace parser {
// @public (undocumented)
export type Path = ReadonlyArray<string | number>;

// @public (undocumented)
interface PendingPromise<TValue> extends Promise<TValue> {
// (undocumented)
status: "pending";
}

// @public (undocumented)
class Policies {
constructor(config: {
Expand Down Expand Up @@ -1907,6 +1921,16 @@ interface Printer {
(node: ASTNode, originalPrint: typeof print_2): string;
}

// @public (undocumented)
const PROMISE_SYMBOL: unique symbol;

// Warning: (ae-forgotten-export) The symbol "PendingPromise" needs to be exported by the entry point index.d.ts
// Warning: (ae-forgotten-export) The symbol "FulfilledPromise" needs to be exported by the entry point index.d.ts
// Warning: (ae-forgotten-export) The symbol "RejectedPromise" needs to be exported by the entry point index.d.ts
//
// @public (undocumented)
type PromiseWithState<TValue> = PendingPromise<TValue> | FulfilledPromise<TValue> | RejectedPromise<TValue>;

// @public (undocumented)
const QUERY_REFERENCE_SYMBOL: unique symbol;

Expand Down Expand Up @@ -2153,12 +2177,19 @@ export { QueryOptions }
//
// @public
export interface QueryReference<TData = unknown> {
// (undocumented)
[PROMISE_SYMBOL]: QueryRefPromise<TData>;
// Warning: (ae-forgotten-export) The symbol "InternalQueryReference" needs to be exported by the entry point index.d.ts
//
// (undocumented)
[QUERY_REFERENCE_SYMBOL]: InternalQueryReference<TData>;
readonly [QUERY_REFERENCE_SYMBOL]: InternalQueryReference<TData>;
}

// Warning: (ae-forgotten-export) The symbol "PromiseWithState" needs to be exported by the entry point index.d.ts
//
// @public (undocumented)
type QueryRefPromise<TData> = PromiseWithState<ApolloQueryResult<TData>>;

// @public (undocumented)
export interface QueryResult<TData = any, TVariables extends OperationVariables = OperationVariables> extends ObservableQueryFields<TData, TVariables> {
// (undocumented)
Expand Down Expand Up @@ -2286,6 +2317,14 @@ export type RefetchQueryDescriptor = string | DocumentNode;
// @public (undocumented)
export type RefetchWritePolicy = "merge" | "overwrite";

// @public (undocumented)
interface RejectedPromise<TValue> extends Promise<TValue> {
// (undocumented)
reason: unknown;
// (undocumented)
status: "rejected";
}

// @public (undocumented)
class RenderPromises {
// (undocumented)
Expand Down Expand Up @@ -2862,8 +2901,8 @@ interface WriteContext extends ReadMergeModifyContext {
// src/core/QueryManager.ts:395:7 - (ae-forgotten-export) The symbol "UpdateQueries" 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/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
// src/react/hooks/useBackgroundQuery.ts:27:3 - (ae-forgotten-export) The symbol "RefetchFunction" needs to be exported by the entry point index.d.ts
// src/react/hooks/useBackgroundQuery.ts:30:3 - (ae-forgotten-export) The symbol "FetchMoreFunction" needs to be exported by the entry point index.d.ts
// src/react/hooks/useBackgroundQuery.ts:31:3 - (ae-forgotten-export) The symbol "RefetchFunction" needs to be exported by the entry point index.d.ts
// src/react/hooks/useLoadableQuery.ts:49:5 - (ae-forgotten-export) The symbol "ResetFunction" needs to be exported by the entry point index.d.ts

// (No @packageDocumentation comment for this package)
Expand Down
4 changes: 2 additions & 2 deletions .size-limits.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"dist/apollo-client.min.cjs": 38632,
"import { ApolloClient, InMemoryCache, HttpLink } from \"dist/index.js\" (production)": 32319
"dist/apollo-client.min.cjs": 38618,
"import { ApolloClient, InMemoryCache, HttpLink } from \"dist/index.js\" (production)": 32318
}
Loading