Skip to content

Commit da515f5

Browse files
committed
refine filtering
We can stop checking for errors that will "filter" child futures once we have reached the point in the path at which the current incrementalContext was branched.
1 parent 4cd2361 commit da515f5

File tree

2 files changed

+44
-18
lines changed

2 files changed

+44
-18
lines changed

src/execution/IncrementalPublisher.ts

+7-3
Original file line numberDiff line numberDiff line change
@@ -638,6 +638,7 @@ export function isDeferredGroupedFieldSetRecord(
638638

639639
export interface IncrementalContext {
640640
deferUsageSet: DeferUsageSet | undefined;
641+
path: Path | undefined;
641642
errors: Array<GraphQLError>;
642643
errorPaths: Set<Path>;
643644
futures: Array<Future>;
@@ -689,16 +690,17 @@ export class DeferredGroupedFieldSetRecord {
689690

690691
const incrementalContext: IncrementalContext = {
691692
deferUsageSet,
693+
path,
692694
errors: [],
693695
errorPaths: new Set(),
694696
futures: [],
695697
};
696698

697-
for (const deferredFragmentRecord of this.deferredFragmentRecords) {
699+
for (const deferredFragmentRecord of deferredFragmentRecords) {
698700
deferredFragmentRecord.deferredGroupedFieldSetRecords.push(this);
699701
}
700702

701-
this.result = this.deferredFragmentRecords.some(
703+
this.result = deferredFragmentRecords.some(
702704
(deferredFragmentRecord) => deferredFragmentRecord.id !== undefined,
703705
)
704706
? executor(incrementalContext)
@@ -777,14 +779,16 @@ export class StreamItemsRecord {
777779

778780
constructor(opts: {
779781
streamRecord: StreamRecord;
782+
itemPath?: Path | undefined;
780783
executor: (
781784
incrementalContext: IncrementalContext,
782785
) => PromiseOrValue<StreamItemsResult>;
783786
}) {
784-
const { streamRecord, executor } = opts;
787+
const { streamRecord, itemPath, executor } = opts;
785788
this.streamRecord = streamRecord;
786789
const incrementalContext: IncrementalContext = {
787790
deferUsageSet: undefined,
791+
path: itemPath,
788792
errors: [],
789793
errorPaths: new Set(),
790794
futures: [],

src/execution/execute.ts

+37-15
Original file line numberDiff line numberDiff line change
@@ -293,14 +293,15 @@ function buildDataResponse(
293293
futures: ReadonlyArray<Future>,
294294
cancellableStreams: Set<StreamRecord>,
295295
): ExecutionResult | ExperimentalIncrementalExecutionResults {
296-
const filteredFutures = filterFutures(errorPaths, futures);
296+
const filteredFutures = filterFutures(undefined, errorPaths, futures);
297297
if (filteredFutures.length > 0) {
298298
return buildIncrementalResponse(data, errors, futures, cancellableStreams);
299299
}
300300
return errors.length > 0 ? { errors, data } : { data };
301301
}
302302

303303
function filterFutures(
304+
initialPath: Path | undefined,
304305
errorPaths: ReadonlySet<Path | undefined>,
305306
futures: ReadonlyArray<Future>,
306307
): ReadonlyArray<Future> {
@@ -310,19 +311,33 @@ function filterFutures(
310311

311312
const filteredFutures: Array<Future> = [];
312313
for (const future of futures) {
313-
let currentPath = isDeferredGroupedFieldSetRecord(future)
314+
let currentPath: Path | undefined = isDeferredGroupedFieldSetRecord(future)
314315
? future.path
315316
: future.streamRecord.path;
316-
while (currentPath !== undefined) {
317+
318+
if (errorPaths.has(currentPath)) {
319+
continue;
320+
}
321+
322+
const paths: Array<Path | undefined> = [currentPath];
323+
let filtered = false;
324+
while (currentPath !== initialPath) {
325+
// Because currentPath leads to initialPath or is undefined, and the
326+
// loop will exit if initialPath is undefined, currentPath must be
327+
// defined.
328+
// TODO: Consider, however, adding an invariant.
329+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
330+
currentPath = currentPath!.prev;
317331
if (errorPaths.has(currentPath)) {
332+
filtered = true;
318333
break;
319334
}
320-
currentPath = currentPath.prev;
335+
paths.push(currentPath);
321336
}
322-
if (errorPaths.has(currentPath)) {
323-
continue;
337+
338+
if (!filtered) {
339+
filteredFutures.push(future);
324340
}
325-
filteredFutures.push(future);
326341
}
327342

328343
return filteredFutures;
@@ -1966,7 +1981,7 @@ function executeDeferredGroupedFieldSet(
19661981
deferredFragmentRecords,
19671982
path: pathToArray(path),
19681983
data: resolved,
1969-
futures: filterFutures(errorPaths, futures),
1984+
futures: filterFutures(path, errorPaths, futures),
19701985
errors,
19711986
}),
19721987
(error) => {
@@ -1985,7 +2000,7 @@ function executeDeferredGroupedFieldSet(
19852000
deferredFragmentRecords,
19862001
path: pathToArray(path),
19872002
data,
1988-
futures: filterFutures(errorPaths, futures),
2003+
futures: filterFutures(path, errorPaths, futures),
19892004
errors,
19902005
};
19912006
}
@@ -2015,6 +2030,7 @@ function firstSyncStreamItems(
20152030

20162031
const firstStreamItems = new StreamItemsRecord({
20172032
streamRecord,
2033+
itemPath: initialPath,
20182034
executor: (incrementalContext) =>
20192035
Promise.resolve().then(() => {
20202036
const firstResult = executor(
@@ -2033,6 +2049,7 @@ function firstSyncStreamItems(
20332049

20342050
const nextStreamItems = new StreamItemsRecord({
20352051
streamRecord,
2052+
itemPath: currentPath,
20362053
executor: (nextIncrementalContext) =>
20372054
executor(currentPath, item, nextIncrementalContext),
20382055
});
@@ -2065,8 +2082,10 @@ function firstAsyncStreamItems(
20652082
incrementalContext: IncrementalContext,
20662083
) => PromiseOrValue<StreamItemsResult>,
20672084
): StreamItemsRecord {
2085+
const initialPath = addPath(path, initialIndex, undefined);
20682086
const firstStreamItems: StreamItemsRecord = new StreamItemsRecord({
20692087
streamRecord,
2088+
itemPath: initialPath,
20702089
executor: (incrementalContext) =>
20712090
Promise.resolve().then(() =>
20722091
getNextAsyncStreamItemsResult(
@@ -2120,7 +2139,8 @@ async function getNextAsyncStreamItemsResult(
21202139
const nextStreamItems: StreamItemsRecord = nextAsyncStreamItems(
21212140
streamRecord,
21222141
path,
2123-
index + 1,
2142+
itemPath,
2143+
index,
21242144
nodes,
21252145
asyncIterator,
21262146
executor,
@@ -2133,6 +2153,7 @@ async function getNextAsyncStreamItemsResult(
21332153
function nextAsyncStreamItems(
21342154
streamRecord: StreamRecord,
21352155
path: Path,
2156+
initialPath: Path,
21362157
initialIndex: number,
21372158
nodes: ReadonlyArray<FieldNode>,
21382159
asyncIterator: AsyncIterator<unknown>,
@@ -2144,13 +2165,14 @@ function nextAsyncStreamItems(
21442165
): StreamItemsRecord {
21452166
const nextStreamItems: StreamItemsRecord = new StreamItemsRecord({
21462167
streamRecord,
2168+
itemPath: initialPath,
21472169
executor: (incrementalContext) =>
21482170
Promise.resolve().then(() =>
21492171
getNextAsyncStreamItemsResult(
21502172
streamRecord,
21512173
nextStreamItems,
21522174
path,
2153-
initialIndex,
2175+
initialIndex + 1,
21542176
incrementalContext,
21552177
nodes,
21562178
asyncIterator,
@@ -2171,7 +2193,7 @@ function completeStreamItems(
21712193
info: GraphQLResolveInfo,
21722194
itemType: GraphQLOutputType,
21732195
): PromiseOrValue<StreamItemsResult> {
2174-
const { errors, errorPaths, futures } = incrementalContext;
2196+
const { path, errors, errorPaths, futures } = incrementalContext;
21752197
if (isPromise(item)) {
21762198
return completePromisedValue(
21772199
exeContext,
@@ -2186,7 +2208,7 @@ function completeStreamItems(
21862208
(resolvedItem) => ({
21872209
streamRecord,
21882210
items: [resolvedItem],
2189-
futures: filterFutures(errorPaths, futures),
2211+
futures: filterFutures(path, errorPaths, futures),
21902212
errors,
21912213
}),
21922214
(error) => {
@@ -2250,7 +2272,7 @@ function completeStreamItems(
22502272
(resolvedItem) => ({
22512273
streamRecord,
22522274
items: [resolvedItem],
2253-
futures: filterFutures(errorPaths, futures),
2275+
futures: filterFutures(path, errorPaths, futures),
22542276
errors,
22552277
}),
22562278
(error) => {
@@ -2267,7 +2289,7 @@ function completeStreamItems(
22672289
return {
22682290
streamRecord,
22692291
items: [completedItem],
2270-
futures: filterFutures(errorPaths, futures),
2292+
futures: filterFutures(path, errorPaths, futures),
22712293
errors,
22722294
};
22732295
}

0 commit comments

Comments
 (0)