Skip to content

Commit 857b440

Browse files
authored
defer/stream: use Set for subsequentPayloads (#3717)
1 parent 5a41f86 commit 857b440

File tree

1 file changed

+29
-31
lines changed

1 file changed

+29
-31
lines changed

src/execution/execute.ts

Lines changed: 29 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ export interface ExecutionContext {
121121
typeResolver: GraphQLTypeResolver<any, any>;
122122
subscribeFieldResolver: GraphQLFieldResolver<any, any>;
123123
errors: Array<GraphQLError>;
124-
subsequentPayloads: Array<AsyncPayloadRecord>;
124+
subsequentPayloads: Set<AsyncPayloadRecord>;
125125
}
126126

127127
/**
@@ -350,7 +350,7 @@ function executeImpl(
350350
return result.then(
351351
(data) => {
352352
const initialResult = buildResponse(data, exeContext.errors);
353-
if (exeContext.subsequentPayloads.length > 0) {
353+
if (exeContext.subsequentPayloads.size > 0) {
354354
return {
355355
initialResult: {
356356
...initialResult,
@@ -368,7 +368,7 @@ function executeImpl(
368368
);
369369
}
370370
const initialResult = buildResponse(result, exeContext.errors);
371-
if (exeContext.subsequentPayloads.length > 0) {
371+
if (exeContext.subsequentPayloads.size > 0) {
372372
return {
373373
initialResult: {
374374
...initialResult,
@@ -496,7 +496,7 @@ export function buildExecutionContext(
496496
fieldResolver: fieldResolver ?? defaultFieldResolver,
497497
typeResolver: typeResolver ?? defaultTypeResolver,
498498
subscribeFieldResolver: subscribeFieldResolver ?? defaultFieldResolver,
499-
subsequentPayloads: [],
499+
subsequentPayloads: new Set(),
500500
errors: [],
501501
};
502502
}
@@ -1808,7 +1808,7 @@ function executeDeferredFragment(
18081808
promiseOrData = null;
18091809
}
18101810
asyncPayloadRecord.addData(promiseOrData);
1811-
exeContext.subsequentPayloads.push(asyncPayloadRecord);
1811+
exeContext.subsequentPayloads.add(asyncPayloadRecord);
18121812
}
18131813

18141814
function executeStreamField(
@@ -1873,7 +1873,7 @@ function executeStreamField(
18731873
} catch (error) {
18741874
asyncPayloadRecord.errors.push(error);
18751875
asyncPayloadRecord.addItems(null);
1876-
exeContext.subsequentPayloads.push(asyncPayloadRecord);
1876+
exeContext.subsequentPayloads.add(asyncPayloadRecord);
18771877
return asyncPayloadRecord;
18781878
}
18791879

@@ -1890,7 +1890,7 @@ function executeStreamField(
18901890
}
18911891

18921892
asyncPayloadRecord.addItems(completedItems);
1893-
exeContext.subsequentPayloads.push(asyncPayloadRecord);
1893+
exeContext.subsequentPayloads.add(asyncPayloadRecord);
18941894
return asyncPayloadRecord;
18951895
}
18961896

@@ -1992,7 +1992,7 @@ async function executeStreamIterator(
19921992
},
19931993
),
19941994
);
1995-
subsequentPayloads.push(asyncPayloadRecord);
1995+
subsequentPayloads.add(asyncPayloadRecord);
19961996
try {
19971997
// eslint-disable-next-line no-await-in-loop
19981998
const { done } = await dataPromise;
@@ -2015,7 +2015,7 @@ function yieldSubsequentPayloads(
20152015
async function race(): Promise<
20162016
IteratorResult<SubsequentIncrementalExecutionResult>
20172017
> {
2018-
if (exeContext.subsequentPayloads.length === 0) {
2018+
if (exeContext.subsequentPayloads.size === 0) {
20192019
// async iterable resolver just finished and no more pending payloads
20202020
return {
20212021
value: {
@@ -2041,17 +2041,16 @@ function yieldSubsequentPayloads(
20412041
},
20422042
);
20432043

2044-
if (exeContext.subsequentPayloads.length === 0) {
2044+
if (exeContext.subsequentPayloads.size === 0) {
20452045
// a different call to next has exhausted all payloads
20462046
return { value: undefined, done: true };
20472047
}
2048-
const index = exeContext.subsequentPayloads.indexOf(asyncPayloadRecord);
2049-
if (index === -1) {
2048+
if (!exeContext.subsequentPayloads.has(asyncPayloadRecord)) {
20502049
// a different call to next has consumed this payload
20512050
return race();
20522051
}
20532052

2054-
exeContext.subsequentPayloads.splice(index, 1);
2053+
exeContext.subsequentPayloads.delete(asyncPayloadRecord);
20552054

20562055
const incrementalResult: IncrementalResult = {};
20572056
if (isStreamPayload(asyncPayloadRecord)) {
@@ -2079,47 +2078,46 @@ function yieldSubsequentPayloads(
20792078
return {
20802079
value: {
20812080
incremental: [incrementalResult],
2082-
hasNext: exeContext.subsequentPayloads.length > 0,
2081+
hasNext: exeContext.subsequentPayloads.size > 0,
20832082
},
20842083
done: false,
20852084
};
20862085
}
20872086

2087+
function returnStreamIterators() {
2088+
const promises: Array<Promise<IteratorResult<unknown>>> = [];
2089+
exeContext.subsequentPayloads.forEach((asyncPayloadRecord) => {
2090+
if (
2091+
isStreamPayload(asyncPayloadRecord) &&
2092+
asyncPayloadRecord.iterator?.return
2093+
) {
2094+
promises.push(asyncPayloadRecord.iterator.return());
2095+
}
2096+
});
2097+
return Promise.all(promises);
2098+
}
2099+
20882100
return {
20892101
[Symbol.asyncIterator]() {
20902102
return this;
20912103
},
20922104
next: () => {
2093-
if (exeContext.subsequentPayloads.length === 0 || isDone) {
2105+
if (exeContext.subsequentPayloads.size === 0 || isDone) {
20942106
return Promise.resolve({ value: undefined, done: true });
20952107
}
20962108
return race();
20972109
},
20982110
async return(): Promise<
20992111
IteratorResult<SubsequentIncrementalExecutionResult, void>
21002112
> {
2101-
await Promise.all(
2102-
exeContext.subsequentPayloads.map((asyncPayloadRecord) => {
2103-
if (isStreamPayload(asyncPayloadRecord)) {
2104-
return asyncPayloadRecord.iterator?.return?.();
2105-
}
2106-
return undefined;
2107-
}),
2108-
);
2113+
await returnStreamIterators();
21092114
isDone = true;
21102115
return { value: undefined, done: true };
21112116
},
21122117
async throw(
21132118
error?: unknown,
21142119
): Promise<IteratorResult<SubsequentIncrementalExecutionResult, void>> {
2115-
await Promise.all(
2116-
exeContext.subsequentPayloads.map((asyncPayloadRecord) => {
2117-
if (isStreamPayload(asyncPayloadRecord)) {
2118-
return asyncPayloadRecord.iterator?.return?.();
2119-
}
2120-
return undefined;
2121-
}),
2122-
);
2120+
await returnStreamIterators();
21232121
isDone = true;
21242122
return Promise.reject(error);
21252123
},

0 commit comments

Comments
 (0)