Skip to content

Commit 6fecd95

Browse files
committed
consolidate payloads
1 parent 04be954 commit 6fecd95

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
@@ -109,6 +109,12 @@ export interface FormattedCompletedResult {
109109
errors?: ReadonlyArray<GraphQLError>;
110110
}
111111

112+
interface IncrementalAggregate {
113+
newPendingSources: Set<DeferredFragmentRecord | StreamRecord>;
114+
incrementalResults: Array<IncrementalResult>;
115+
completedResults: Array<CompletedResult>;
116+
}
117+
112118
/**
113119
* This class is used to publish incremental results to the client, enabling semi-concurrent
114120
* execution while preserving result order.
@@ -179,20 +185,28 @@ export class IncrementalPublisher {
179185
return { value: undefined, done: true };
180186
}
181187

182-
for (const item of this._released) {
183-
this._pending.delete(item);
184-
}
185-
const released = this._released;
186-
this._released = new Set();
188+
if (this._released.size > 0) {
189+
let aggregate = this._incrementalInitializer();
190+
do {
191+
for (const item of this._released) {
192+
this._pending.delete(item);
193+
}
194+
const released = this._released;
195+
this._released = new Set();
187196

188-
const result = this._getIncrementalResult(released);
197+
aggregate = this._incrementalReducer(aggregate, released);
198+
} while (this._released.size > 0);
189199

190-
if (!this.hasNext()) {
191-
isDone = true;
192-
}
200+
const hasNext = this.hasNext();
201+
202+
if (!hasNext) {
203+
isDone = true;
204+
}
193205

194-
if (result !== undefined) {
195-
return { value: result, done: false };
206+
return {
207+
value: this._incrementalFinalizer(aggregate),
208+
done: false,
209+
};
196210
}
197211

198212
// eslint-disable-next-line no-await-in-loop
@@ -542,37 +556,20 @@ export class IncrementalPublisher {
542556
this._trigger();
543557
}
544558

545-
private _getIncrementalResult(
546-
completedRecords: ReadonlySet<SubsequentResultRecord>,
547-
): SubsequentIncrementalExecutionResult | undefined {
548-
const { pending, incremental, completed } =
549-
this._processPending(completedRecords);
550-
551-
const hasNext = this.hasNext();
552-
if (incremental.length === 0 && completed.length === 0 && hasNext) {
553-
return undefined;
554-
}
555-
556-
const result: SubsequentIncrementalExecutionResult = { hasNext };
557-
if (pending.length) {
558-
result.pending = pending;
559-
}
560-
if (incremental.length) {
561-
result.incremental = incremental;
562-
}
563-
if (completed.length) {
564-
result.completed = completed;
565-
}
566-
567-
return result;
559+
private _incrementalInitializer(): IncrementalAggregate {
560+
return {
561+
newPendingSources: new Set<DeferredFragmentRecord | StreamRecord>(),
562+
incrementalResults: [],
563+
completedResults: [],
564+
};
568565
}
569566

570-
private _processPending(
567+
private _incrementalReducer(
568+
aggregate: IncrementalAggregate,
571569
completedRecords: ReadonlySet<SubsequentResultRecord>,
572-
): IncrementalUpdate {
573-
const newPendingSources = new Set<DeferredFragmentRecord | StreamRecord>();
574-
const incrementalResults: Array<IncrementalResult> = [];
575-
const completedResults: Array<CompletedResult> = [];
570+
): IncrementalAggregate {
571+
const { newPendingSources, incrementalResults, completedResults } =
572+
aggregate;
576573
for (const subsequentResultRecord of completedRecords) {
577574
for (const child of subsequentResultRecord.children) {
578575
const pendingSource = isStreamItemsRecord(child)
@@ -635,11 +632,30 @@ export class IncrementalPublisher {
635632
}
636633
}
637634

638-
return {
639-
pending: this.pendingSourcesToResults(newPendingSources),
640-
incremental: incrementalResults,
641-
completed: completedResults,
635+
return aggregate;
636+
}
637+
638+
private _incrementalFinalizer(
639+
aggregate: IncrementalAggregate,
640+
): SubsequentIncrementalExecutionResult {
641+
const { newPendingSources, incrementalResults, completedResults } =
642+
aggregate;
643+
const pendingResults = this.pendingSourcesToResults(newPendingSources);
644+
645+
const result: SubsequentIncrementalExecutionResult = {
646+
hasNext: this.hasNext(),
642647
};
648+
if (pendingResults.length) {
649+
result.pending = pendingResults;
650+
}
651+
if (incrementalResults.length) {
652+
result.incremental = incrementalResults;
653+
}
654+
if (completedResults.length) {
655+
result.completed = completedResults;
656+
}
657+
658+
return result;
643659
}
644660

645661
private _completedRecordToResult(

src/execution/__tests__/defer-test.ts

+11-37
Original file line numberDiff line numberDiff line change
@@ -1084,35 +1084,25 @@ describe('Execute: defer directive', () => {
10841084
hasNext: true,
10851085
},
10861086
{
1087-
pending: [{ path: ['hero', 'nestedObject'] }],
10881087
incremental: [
10891088
{
10901089
data: { bar: 'bar' },
10911090
path: ['hero', 'nestedObject', 'deeperObject'],
10921091
},
1093-
],
1094-
completed: [{ path: ['hero'] }],
1095-
hasNext: true,
1096-
},
1097-
{
1098-
pending: [{ path: ['hero', 'nestedObject', 'deeperObject'] }],
1099-
incremental: [
11001092
{
11011093
data: { baz: 'baz' },
11021094
path: ['hero', 'nestedObject', 'deeperObject'],
11031095
},
1104-
],
1105-
hasNext: true,
1106-
completed: [{ path: ['hero', 'nestedObject'] }],
1107-
},
1108-
{
1109-
incremental: [
11101096
{
11111097
data: { bak: 'bak' },
11121098
path: ['hero', 'nestedObject', 'deeperObject'],
11131099
},
11141100
],
1115-
completed: [{ path: ['hero', 'nestedObject', 'deeperObject'] }],
1101+
completed: [
1102+
{ path: ['hero'] },
1103+
{ path: ['hero', 'nestedObject'] },
1104+
{ path: ['hero', 'nestedObject', 'deeperObject'] },
1105+
],
11161106
hasNext: false,
11171107
},
11181108
]);
@@ -1159,31 +1149,25 @@ describe('Execute: defer directive', () => {
11591149
hasNext: true,
11601150
},
11611151
{
1162-
pending: [{ path: ['hero', 'nestedObject', 'deeperObject'] }],
11631152
incremental: [
11641153
{
11651154
data: {
11661155
foo: 'foo',
11671156
},
11681157
path: ['hero', 'nestedObject', 'deeperObject'],
11691158
},
1170-
],
1171-
completed: [
1172-
{ path: ['hero'] },
1173-
{ path: ['hero', 'nestedObject', 'deeperObject'] },
1174-
],
1175-
hasNext: true,
1176-
},
1177-
{
1178-
incremental: [
11791159
{
11801160
data: {
11811161
bar: 'bar',
11821162
},
11831163
path: ['hero', 'nestedObject', 'deeperObject'],
11841164
},
11851165
],
1186-
completed: [{ path: ['hero', 'nestedObject', 'deeperObject'] }],
1166+
completed: [
1167+
{ path: ['hero'] },
1168+
{ path: ['hero', 'nestedObject', 'deeperObject'] },
1169+
{ path: ['hero', 'nestedObject', 'deeperObject'] },
1170+
],
11871171
hasNext: false,
11881172
},
11891173
]);
@@ -1979,27 +1963,17 @@ describe('Execute: defer directive', () => {
19791963
hasNext: true,
19801964
},
19811965
{
1982-
pending: [
1983-
{ path: ['hero', 'friends', 0] },
1984-
{ path: ['hero', 'friends', 1] },
1985-
{ path: ['hero', 'friends', 2] },
1986-
],
19871966
incremental: [
19881967
{
19891968
data: { name: 'slow', friends: [{}, {}, {}] },
19901969
path: ['hero'],
19911970
},
1992-
],
1993-
completed: [{ path: ['hero'] }],
1994-
hasNext: true,
1995-
},
1996-
{
1997-
incremental: [
19981971
{ data: { name: 'Han' }, path: ['hero', 'friends', 0] },
19991972
{ data: { name: 'Leia' }, path: ['hero', 'friends', 1] },
20001973
{ data: { name: 'C-3PO' }, path: ['hero', 'friends', 2] },
20011974
],
20021975
completed: [
1976+
{ path: ['hero'] },
20031977
{ path: ['hero', 'friends', 0] },
20041978
{ path: ['hero', 'friends', 1] },
20051979
{ path: ['hero', 'friends', 2] },

0 commit comments

Comments
 (0)