Skip to content

Commit ce59304

Browse files
committed
consolidate payloads
1 parent e62ca02 commit ce59304

File tree

3 files changed

+91
-167
lines changed

3 files changed

+91
-167
lines changed

src/execution/IncrementalPublisher.ts

+59-43
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,12 @@ export interface FormattedCompletedResult {
162162
errors?: ReadonlyArray<GraphQLError>;
163163
}
164164

165+
interface IncrementalAggregate {
166+
newPendingSources: Set<DeferredFragmentRecord | StreamRecord>;
167+
incrementalResults: Array<IncrementalResult>;
168+
completedResults: Array<CompletedResult>;
169+
}
170+
165171
/**
166172
* This class is used to publish incremental results to the client, enabling semi-concurrent
167173
* execution while preserving result order.
@@ -399,20 +405,28 @@ export class IncrementalPublisher {
399405
return { value: undefined, done: true };
400406
}
401407

402-
for (const item of this._released) {
403-
this._pending.delete(item);
404-
}
405-
const released = this._released;
406-
this._released = new Set();
408+
if (this._released.size > 0) {
409+
let aggregate = this._incrementalInitializer();
410+
do {
411+
for (const item of this._released) {
412+
this._pending.delete(item);
413+
}
414+
const released = this._released;
415+
this._released = new Set();
407416

408-
const result = this._getIncrementalResult(released);
417+
aggregate = this._incrementalReducer(aggregate, released);
418+
} while (this._released.size > 0);
409419

410-
if (this._pending.size === 0) {
411-
isDone = true;
412-
}
420+
const hasNext = this._pending.size > 0;
421+
422+
if (!hasNext) {
423+
isDone = true;
424+
}
413425

414-
if (result !== undefined) {
415-
return { value: result, done: false };
426+
return {
427+
value: this._incrementalFinalizer(aggregate),
428+
done: false,
429+
};
416430
}
417431

418432
// eslint-disable-next-line no-await-in-loop
@@ -494,37 +508,20 @@ export class IncrementalPublisher {
494508
this._trigger();
495509
}
496510

497-
private _getIncrementalResult(
498-
completedRecords: ReadonlySet<SubsequentResultRecord>,
499-
): SubsequentIncrementalExecutionResult | undefined {
500-
const { pending, incremental, completed } =
501-
this._processPending(completedRecords);
502-
503-
const hasNext = this._pending.size > 0;
504-
if (incremental.length === 0 && completed.length === 0 && hasNext) {
505-
return undefined;
506-
}
507-
508-
const result: SubsequentIncrementalExecutionResult = { hasNext };
509-
if (pending.length) {
510-
result.pending = pending;
511-
}
512-
if (incremental.length) {
513-
result.incremental = incremental;
514-
}
515-
if (completed.length) {
516-
result.completed = completed;
517-
}
518-
519-
return result;
511+
private _incrementalInitializer(): IncrementalAggregate {
512+
return {
513+
newPendingSources: new Set<DeferredFragmentRecord | StreamRecord>(),
514+
incrementalResults: [],
515+
completedResults: [],
516+
};
520517
}
521518

522-
private _processPending(
519+
private _incrementalReducer(
520+
aggregate: IncrementalAggregate,
523521
completedRecords: ReadonlySet<SubsequentResultRecord>,
524-
): IncrementalUpdate {
525-
const newPendingSources = new Set<DeferredFragmentRecord | StreamRecord>();
526-
const incrementalResults: Array<IncrementalResult> = [];
527-
const completedResults: Array<CompletedResult> = [];
522+
): IncrementalAggregate {
523+
const { newPendingSources, incrementalResults, completedResults } =
524+
aggregate;
528525
for (const subsequentResultRecord of completedRecords) {
529526
for (const child of subsequentResultRecord.children) {
530527
if (child.filtered) {
@@ -585,11 +582,30 @@ export class IncrementalPublisher {
585582
}
586583
}
587584

588-
return {
589-
pending: this.pendingSourcesToResults(newPendingSources),
590-
incremental: incrementalResults,
591-
completed: completedResults,
585+
return aggregate;
586+
}
587+
588+
private _incrementalFinalizer(
589+
aggregate: IncrementalAggregate,
590+
): SubsequentIncrementalExecutionResult {
591+
const { newPendingSources, incrementalResults, completedResults } =
592+
aggregate;
593+
const pendingResults = this.pendingSourcesToResults(newPendingSources);
594+
595+
const result: SubsequentIncrementalExecutionResult = {
596+
hasNext: this._pending.size > 0,
592597
};
598+
if (pendingResults.length) {
599+
result.pending = pendingResults;
600+
}
601+
if (incrementalResults.length) {
602+
result.incremental = incrementalResults;
603+
}
604+
if (completedResults.length) {
605+
result.completed = completedResults;
606+
}
607+
608+
return result;
593609
}
594610

595611
private _completedRecordToResult(

src/execution/__tests__/defer-test.ts

+11-37
Original file line numberDiff line numberDiff line change
@@ -1177,35 +1177,25 @@ describe('Execute: defer directive', () => {
11771177
hasNext: true,
11781178
},
11791179
{
1180-
pending: [{ path: ['hero', 'nestedObject'] }],
11811180
incremental: [
11821181
{
11831182
data: { bar: 'bar' },
11841183
path: ['hero', 'nestedObject', 'deeperObject'],
11851184
},
1186-
],
1187-
completed: [{ path: ['hero'] }],
1188-
hasNext: true,
1189-
},
1190-
{
1191-
pending: [{ path: ['hero', 'nestedObject', 'deeperObject'] }],
1192-
incremental: [
11931185
{
11941186
data: { baz: 'baz' },
11951187
path: ['hero', 'nestedObject', 'deeperObject'],
11961188
},
1197-
],
1198-
hasNext: true,
1199-
completed: [{ path: ['hero', 'nestedObject'] }],
1200-
},
1201-
{
1202-
incremental: [
12031189
{
12041190
data: { bak: 'bak' },
12051191
path: ['hero', 'nestedObject', 'deeperObject'],
12061192
},
12071193
],
1208-
completed: [{ path: ['hero', 'nestedObject', 'deeperObject'] }],
1194+
completed: [
1195+
{ path: ['hero'] },
1196+
{ path: ['hero', 'nestedObject'] },
1197+
{ path: ['hero', 'nestedObject', 'deeperObject'] },
1198+
],
12091199
hasNext: false,
12101200
},
12111201
]);
@@ -1254,31 +1244,25 @@ describe('Execute: defer directive', () => {
12541244
hasNext: true,
12551245
},
12561246
{
1257-
pending: [{ path: ['hero', 'nestedObject', 'deeperObject'] }],
12581247
incremental: [
12591248
{
12601249
data: {
12611250
foo: 'foo',
12621251
},
12631252
path: ['hero', 'nestedObject', 'deeperObject'],
12641253
},
1265-
],
1266-
completed: [
1267-
{ path: ['hero'] },
1268-
{ path: ['hero', 'nestedObject', 'deeperObject'] },
1269-
],
1270-
hasNext: true,
1271-
},
1272-
{
1273-
incremental: [
12741254
{
12751255
data: {
12761256
bar: 'bar',
12771257
},
12781258
path: ['hero', 'nestedObject', 'deeperObject'],
12791259
},
12801260
],
1281-
completed: [{ path: ['hero', 'nestedObject', 'deeperObject'] }],
1261+
completed: [
1262+
{ path: ['hero'] },
1263+
{ path: ['hero', 'nestedObject', 'deeperObject'] },
1264+
{ path: ['hero', 'nestedObject', 'deeperObject'] },
1265+
],
12821266
hasNext: false,
12831267
},
12841268
]);
@@ -2101,27 +2085,17 @@ describe('Execute: defer directive', () => {
21012085
hasNext: true,
21022086
},
21032087
{
2104-
pending: [
2105-
{ path: ['hero', 'friends', 0] },
2106-
{ path: ['hero', 'friends', 1] },
2107-
{ path: ['hero', 'friends', 2] },
2108-
],
21092088
incremental: [
21102089
{
21112090
data: { name: 'slow', friends: [{}, {}, {}] },
21122091
path: ['hero'],
21132092
},
2114-
],
2115-
completed: [{ path: ['hero'] }],
2116-
hasNext: true,
2117-
},
2118-
{
2119-
incremental: [
21202093
{ data: { name: 'Han' }, path: ['hero', 'friends', 0] },
21212094
{ data: { name: 'Leia' }, path: ['hero', 'friends', 1] },
21222095
{ data: { name: 'C-3PO' }, path: ['hero', 'friends', 2] },
21232096
],
21242097
completed: [
2098+
{ path: ['hero'] },
21252099
{ path: ['hero', 'friends', 0] },
21262100
{ path: ['hero', 'friends', 1] },
21272101
{ path: ['hero', 'friends', 2] },

0 commit comments

Comments
 (0)