Skip to content

Commit 13d73d6

Browse files
committed
consolidate payloads
1 parent 7c6e300 commit 13d73d6

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
@@ -169,6 +169,12 @@ export interface FormattedCompletedResult {
169169
errors?: ReadonlyArray<GraphQLError>;
170170
}
171171

172+
interface IncrementalAggregate {
173+
newPendingSources: Set<DeferredFragmentRecord | StreamRecord>;
174+
incrementalResults: Array<IncrementalResult>;
175+
completedResults: Array<CompletedResult>;
176+
}
177+
172178
/**
173179
* This class is used to publish incremental results to the client, enabling semi-concurrent
174180
* execution while preserving result order.
@@ -482,20 +488,28 @@ export class IncrementalPublisher {
482488
return { value: undefined, done: true };
483489
}
484490

485-
for (const item of this._released) {
486-
this._pending.delete(item);
487-
}
488-
const released = this._released;
489-
this._released = new Set();
491+
if (this._released.size > 0) {
492+
let aggregate = this._incrementalInitializer();
493+
do {
494+
for (const item of this._released) {
495+
this._pending.delete(item);
496+
}
497+
const released = this._released;
498+
this._released = new Set();
490499

491-
const result = this._getIncrementalResult(released);
500+
aggregate = this._incrementalReducer(aggregate, released);
501+
} while (this._released.size > 0);
492502

493-
if (this._pending.size === 0) {
494-
isDone = true;
495-
}
503+
const hasNext = this._pending.size > 0;
504+
505+
if (!hasNext) {
506+
isDone = true;
507+
}
496508

497-
if (result !== undefined) {
498-
return { value: result, done: false };
509+
return {
510+
value: this._incrementalFinalizer(aggregate),
511+
done: false,
512+
};
499513
}
500514

501515
// eslint-disable-next-line no-await-in-loop
@@ -577,37 +591,20 @@ export class IncrementalPublisher {
577591
this._trigger();
578592
}
579593

580-
private _getIncrementalResult(
581-
completedRecords: ReadonlySet<SubsequentResultRecord>,
582-
): SubsequentIncrementalExecutionResult | undefined {
583-
const { pending, incremental, completed } =
584-
this._processPending(completedRecords);
585-
586-
const hasNext = this._pending.size > 0;
587-
if (incremental.length === 0 && completed.length === 0 && hasNext) {
588-
return undefined;
589-
}
590-
591-
const result: SubsequentIncrementalExecutionResult = { hasNext };
592-
if (pending.length) {
593-
result.pending = pending;
594-
}
595-
if (incremental.length) {
596-
result.incremental = incremental;
597-
}
598-
if (completed.length) {
599-
result.completed = completed;
600-
}
601-
602-
return result;
594+
private _incrementalInitializer(): IncrementalAggregate {
595+
return {
596+
newPendingSources: new Set<DeferredFragmentRecord | StreamRecord>(),
597+
incrementalResults: [],
598+
completedResults: [],
599+
};
603600
}
604601

605-
private _processPending(
602+
private _incrementalReducer(
603+
aggregate: IncrementalAggregate,
606604
completedRecords: ReadonlySet<SubsequentResultRecord>,
607-
): IncrementalUpdate {
608-
const newPendingSources = new Set<DeferredFragmentRecord | StreamRecord>();
609-
const incrementalResults: Array<IncrementalResult> = [];
610-
const completedResults: Array<CompletedResult> = [];
605+
): IncrementalAggregate {
606+
const { newPendingSources, incrementalResults, completedResults } =
607+
aggregate;
611608
for (const subsequentResultRecord of completedRecords) {
612609
for (const child of subsequentResultRecord.children) {
613610
if (child.filtered) {
@@ -673,11 +670,30 @@ export class IncrementalPublisher {
673670
}
674671
}
675672

676-
return {
677-
pending: this.pendingSourcesToResults(newPendingSources),
678-
incremental: incrementalResults,
679-
completed: completedResults,
673+
return aggregate;
674+
}
675+
676+
private _incrementalFinalizer(
677+
aggregate: IncrementalAggregate,
678+
): SubsequentIncrementalExecutionResult {
679+
const { newPendingSources, incrementalResults, completedResults } =
680+
aggregate;
681+
const pendingResults = this.pendingSourcesToResults(newPendingSources);
682+
683+
const result: SubsequentIncrementalExecutionResult = {
684+
hasNext: this._pending.size > 0,
680685
};
686+
if (pendingResults.length) {
687+
result.pending = pendingResults;
688+
}
689+
if (incrementalResults.length) {
690+
result.incremental = incrementalResults;
691+
}
692+
if (completedResults.length) {
693+
result.completed = completedResults;
694+
}
695+
696+
return result;
681697
}
682698

683699
private _completedRecordToResult(

src/execution/__tests__/defer-test.ts

+11-37
Original file line numberDiff line numberDiff line change
@@ -1174,35 +1174,25 @@ describe('Execute: defer directive', () => {
11741174
hasNext: true,
11751175
},
11761176
{
1177-
pending: [{ path: ['hero', 'nestedObject'] }],
11781177
incremental: [
11791178
{
11801179
data: { bar: 'bar' },
11811180
path: ['hero', 'nestedObject', 'deeperObject'],
11821181
},
1183-
],
1184-
completed: [{ path: ['hero'] }],
1185-
hasNext: true,
1186-
},
1187-
{
1188-
pending: [{ path: ['hero', 'nestedObject', 'deeperObject'] }],
1189-
incremental: [
11901182
{
11911183
data: { baz: 'baz' },
11921184
path: ['hero', 'nestedObject', 'deeperObject'],
11931185
},
1194-
],
1195-
hasNext: true,
1196-
completed: [{ path: ['hero', 'nestedObject'] }],
1197-
},
1198-
{
1199-
incremental: [
12001186
{
12011187
data: { bak: 'bak' },
12021188
path: ['hero', 'nestedObject', 'deeperObject'],
12031189
},
12041190
],
1205-
completed: [{ path: ['hero', 'nestedObject', 'deeperObject'] }],
1191+
completed: [
1192+
{ path: ['hero'] },
1193+
{ path: ['hero', 'nestedObject'] },
1194+
{ path: ['hero', 'nestedObject', 'deeperObject'] },
1195+
],
12061196
hasNext: false,
12071197
},
12081198
]);
@@ -1249,31 +1239,25 @@ describe('Execute: defer directive', () => {
12491239
hasNext: true,
12501240
},
12511241
{
1252-
pending: [{ path: ['hero', 'nestedObject', 'deeperObject'] }],
12531242
incremental: [
12541243
{
12551244
data: {
12561245
foo: 'foo',
12571246
},
12581247
path: ['hero', 'nestedObject', 'deeperObject'],
12591248
},
1260-
],
1261-
completed: [
1262-
{ path: ['hero'] },
1263-
{ path: ['hero', 'nestedObject', 'deeperObject'] },
1264-
],
1265-
hasNext: true,
1266-
},
1267-
{
1268-
incremental: [
12691249
{
12701250
data: {
12711251
bar: 'bar',
12721252
},
12731253
path: ['hero', 'nestedObject', 'deeperObject'],
12741254
},
12751255
],
1276-
completed: [{ path: ['hero', 'nestedObject', 'deeperObject'] }],
1256+
completed: [
1257+
{ path: ['hero'] },
1258+
{ path: ['hero', 'nestedObject', 'deeperObject'] },
1259+
{ path: ['hero', 'nestedObject', 'deeperObject'] },
1260+
],
12771261
hasNext: false,
12781262
},
12791263
]);
@@ -2069,27 +2053,17 @@ describe('Execute: defer directive', () => {
20692053
hasNext: true,
20702054
},
20712055
{
2072-
pending: [
2073-
{ path: ['hero', 'friends', 0] },
2074-
{ path: ['hero', 'friends', 1] },
2075-
{ path: ['hero', 'friends', 2] },
2076-
],
20772056
incremental: [
20782057
{
20792058
data: { name: 'slow', friends: [{}, {}, {}] },
20802059
path: ['hero'],
20812060
},
2082-
],
2083-
completed: [{ path: ['hero'] }],
2084-
hasNext: true,
2085-
},
2086-
{
2087-
incremental: [
20882061
{ data: { name: 'Han' }, path: ['hero', 'friends', 0] },
20892062
{ data: { name: 'Leia' }, path: ['hero', 'friends', 1] },
20902063
{ data: { name: 'C-3PO' }, path: ['hero', 'friends', 2] },
20912064
],
20922065
completed: [
2066+
{ path: ['hero'] },
20932067
{ path: ['hero', 'friends', 0] },
20942068
{ path: ['hero', 'friends', 1] },
20952069
{ path: ['hero', 'friends', 2] },

0 commit comments

Comments
 (0)