@graphql-tools/executor 2.0.0-alpha-20240709212042-9a70c086fa543c594055305622a600bb95343b42 → 2.0.0-alpha-20240804112853-812acba5ea59541106a53f872874fd7aebcffcfc

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  import { createDeferred, isPromise } from '@graphql-tools/utils';
2
2
  import { BoxedPromiseOrValue } from './BoxedPromiseOrValue.js';
3
3
  import { invariant } from './invariant.js';
4
- import { isDeferredFragmentRecord, isDeferredGroupedFieldSetRecord } from './types.js';
4
+ import { isDeferredFragmentRecord, isPendingExecutionGroup } from './types.js';
5
5
  /**
6
6
  * @internal
7
7
  */
@@ -19,15 +19,16 @@ export class IncrementalGraph {
19
19
  this._addIncrementalDataRecords(incrementalDataRecords, undefined, initialResultChildren);
20
20
  return this._promoteNonEmptyToRoot(initialResultChildren);
21
21
  }
22
- addCompletedReconcilableDeferredGroupedFieldSet(reconcilableResult) {
23
- for (const deferredFragmentRecord of reconcilableResult.deferredGroupedFieldSetRecord
24
- .deferredFragmentRecords) {
25
- deferredFragmentRecord.deferredGroupedFieldSetRecords.delete(reconcilableResult.deferredGroupedFieldSetRecord);
26
- deferredFragmentRecord.reconcilableResults.add(reconcilableResult);
22
+ addCompletedSuccessfulExecutionGroup(successfulExecutionGroup) {
23
+ const { pendingExecutionGroup, incrementalDataRecords } = successfulExecutionGroup;
24
+ const deferredFragmentRecords = pendingExecutionGroup.deferredFragmentRecords;
25
+ for (const deferredFragmentRecord of deferredFragmentRecords) {
26
+ const { pendingExecutionGroups, successfulExecutionGroups } = deferredFragmentRecord;
27
+ pendingExecutionGroups.delete(successfulExecutionGroup.pendingExecutionGroup);
28
+ successfulExecutionGroups.add(successfulExecutionGroup);
27
29
  }
28
- const incrementalDataRecords = reconcilableResult.incrementalDataRecords;
29
30
  if (incrementalDataRecords !== undefined) {
30
- this._addIncrementalDataRecords(incrementalDataRecords, reconcilableResult.deferredGroupedFieldSetRecord.deferredFragmentRecords);
31
+ this._addIncrementalDataRecords(incrementalDataRecords, deferredFragmentRecords);
31
32
  }
32
33
  }
33
34
  *currentCompletedBatch() {
@@ -56,42 +57,39 @@ export class IncrementalGraph {
56
57
  }
57
58
  completeDeferredFragment(deferredFragmentRecord) {
58
59
  if (!this._rootNodes.has(deferredFragmentRecord) ||
59
- deferredFragmentRecord.deferredGroupedFieldSetRecords.size > 0) {
60
+ deferredFragmentRecord.pendingExecutionGroups.size > 0) {
60
61
  return;
61
62
  }
62
- const reconcilableResults = Array.from(deferredFragmentRecord.reconcilableResults);
63
- this._removePending(deferredFragmentRecord);
64
- for (const reconcilableResult of reconcilableResults) {
65
- for (const otherDeferredFragmentRecord of reconcilableResult.deferredGroupedFieldSetRecord
63
+ const successfulExecutionGroups = Array.from(deferredFragmentRecord.successfulExecutionGroups);
64
+ this._rootNodes.delete(deferredFragmentRecord);
65
+ for (const successfulExecutionGroup of successfulExecutionGroups) {
66
+ for (const otherDeferredFragmentRecord of successfulExecutionGroup.pendingExecutionGroup
66
67
  .deferredFragmentRecords) {
67
- otherDeferredFragmentRecord.reconcilableResults.delete(reconcilableResult);
68
+ otherDeferredFragmentRecord.successfulExecutionGroups.delete(successfulExecutionGroup);
68
69
  }
69
70
  }
70
71
  const newPending = this._promoteNonEmptyToRoot(deferredFragmentRecord.children);
71
- return { newPending, reconcilableResults };
72
+ return { newPending, successfulExecutionGroups };
72
73
  }
73
74
  removeDeferredFragment(deferredFragmentRecord) {
74
75
  if (!this._rootNodes.has(deferredFragmentRecord)) {
75
76
  return false;
76
77
  }
77
- this._removePending(deferredFragmentRecord);
78
+ this._rootNodes.delete(deferredFragmentRecord);
78
79
  return true;
79
80
  }
80
81
  removeStream(streamRecord) {
81
- this._removePending(streamRecord);
82
- }
83
- _removePending(subsequentResultRecord) {
84
- this._rootNodes.delete(subsequentResultRecord);
82
+ this._rootNodes.delete(streamRecord);
85
83
  }
86
84
  _addIncrementalDataRecords(incrementalDataRecords, parents, initialResultChildren) {
87
85
  for (const incrementalDataRecord of incrementalDataRecords) {
88
- if (isDeferredGroupedFieldSetRecord(incrementalDataRecord)) {
86
+ if (isPendingExecutionGroup(incrementalDataRecord)) {
89
87
  for (const deferredFragmentRecord of incrementalDataRecord.deferredFragmentRecords) {
90
88
  this._addDeferredFragment(deferredFragmentRecord, initialResultChildren);
91
- deferredFragmentRecord.deferredGroupedFieldSetRecords.add(incrementalDataRecord);
89
+ deferredFragmentRecord.pendingExecutionGroups.add(incrementalDataRecord);
92
90
  }
93
91
  if (this._hasPendingFragment(incrementalDataRecord)) {
94
- this._onDeferredGroupedFieldSet(incrementalDataRecord);
92
+ this._onExecutionGroup(incrementalDataRecord);
95
93
  }
96
94
  }
97
95
  else if (parents === undefined) {
@@ -108,49 +106,50 @@ export class IncrementalGraph {
108
106
  }
109
107
  _promoteNonEmptyToRoot(maybeEmptyNewPending) {
110
108
  const newPending = [];
111
- for (const subsequentResultRecord of maybeEmptyNewPending) {
112
- if (isDeferredFragmentRecord(subsequentResultRecord)) {
113
- if (subsequentResultRecord.deferredGroupedFieldSetRecords.size > 0) {
114
- subsequentResultRecord.setAsPending();
115
- for (const deferredGroupedFieldSetRecord of subsequentResultRecord.deferredGroupedFieldSetRecords) {
116
- if (!this._hasPendingFragment(deferredGroupedFieldSetRecord)) {
117
- this._onDeferredGroupedFieldSet(deferredGroupedFieldSetRecord);
109
+ for (const deliveryGroup of maybeEmptyNewPending) {
110
+ if (isDeferredFragmentRecord(deliveryGroup)) {
111
+ if (deliveryGroup.pendingExecutionGroups.size > 0) {
112
+ deliveryGroup.setAsPending();
113
+ for (const pendingExecutionGroup of deliveryGroup.pendingExecutionGroups) {
114
+ if (!this._hasPendingFragment(pendingExecutionGroup)) {
115
+ this._onExecutionGroup(pendingExecutionGroup);
118
116
  }
119
117
  }
120
- this._rootNodes.add(subsequentResultRecord);
121
- newPending.push(subsequentResultRecord);
118
+ this._rootNodes.add(deliveryGroup);
119
+ newPending.push(deliveryGroup);
122
120
  continue;
123
121
  }
124
- for (const child of subsequentResultRecord.children) {
122
+ for (const child of deliveryGroup.children) {
125
123
  maybeEmptyNewPending.add(child);
126
124
  }
127
125
  }
128
126
  else {
129
- this._rootNodes.add(subsequentResultRecord);
130
- newPending.push(subsequentResultRecord);
131
- this._onStreamItems(subsequentResultRecord);
127
+ this._rootNodes.add(deliveryGroup);
128
+ newPending.push(deliveryGroup);
129
+ this._onStreamItems(deliveryGroup);
132
130
  }
133
131
  }
134
132
  return newPending;
135
133
  }
136
- _hasPendingFragment(deferredGroupedFieldSetRecord) {
137
- return deferredGroupedFieldSetRecord.deferredFragmentRecords.some(deferredFragmentRecord => this._rootNodes.has(deferredFragmentRecord));
134
+ _hasPendingFragment(pendingExecutionGroup) {
135
+ return pendingExecutionGroup.deferredFragmentRecords.some(deferredFragmentRecord => this._rootNodes.has(deferredFragmentRecord));
138
136
  }
139
- _addDeferredFragment(deferredFragmentRecord, subsequentResultRecords) {
137
+ _addDeferredFragment(deferredFragmentRecord, deliveryGroups) {
140
138
  if (this._rootNodes.has(deferredFragmentRecord)) {
141
139
  return;
142
140
  }
143
141
  const parent = deferredFragmentRecord.parent;
144
142
  if (parent === undefined) {
145
- invariant(subsequentResultRecords !== undefined);
146
- subsequentResultRecords.add(deferredFragmentRecord);
143
+ invariant(deliveryGroups !== undefined);
144
+ deliveryGroups.add(deferredFragmentRecord);
147
145
  return;
148
146
  }
149
147
  parent.children.add(deferredFragmentRecord);
150
- this._addDeferredFragment(parent, subsequentResultRecords);
148
+ this._addDeferredFragment(parent, deliveryGroups);
151
149
  }
152
- _onDeferredGroupedFieldSet(deferredGroupedFieldSetRecord) {
153
- const result = deferredGroupedFieldSetRecord.result.value;
150
+ _onExecutionGroup(pendingExecutionGroup) {
151
+ const result = pendingExecutionGroup.result
152
+ .value;
154
153
  if (isPromise(result)) {
155
154
  result.then(resolved => this._enqueue(resolved));
156
155
  }
@@ -1,7 +1,7 @@
1
1
  import { addPath, pathToArray } from '@graphql-tools/utils';
2
2
  import { IncrementalGraph } from './IncrementalGraph.js';
3
3
  import { invariant } from './invariant.js';
4
- import { isCancellableStreamRecord, isDeferredGroupedFieldSetResult, isNonReconcilableDeferredGroupedFieldSetResult, } from './types.js';
4
+ import { isCancellableStreamRecord, isCompletedExecutionGroup, isFailedExecutionGroup, } from './types.js';
5
5
  export function buildIncrementalResponse(context, result, errors, incrementalDataRecords) {
6
6
  const incrementalPublisher = new IncrementalPublisher(context);
7
7
  return incrementalPublisher.buildResponse(result, errors, incrementalDataRecords);
@@ -143,17 +143,17 @@ class IncrementalPublisher {
143
143
  };
144
144
  }
145
145
  _handleCompletedIncrementalData(completedIncrementalData, context) {
146
- if (isDeferredGroupedFieldSetResult(completedIncrementalData)) {
147
- this._handleCompletedDeferredGroupedFieldSet(completedIncrementalData, context);
146
+ if (isCompletedExecutionGroup(completedIncrementalData)) {
147
+ this._handleCompletedExecutionGroup(completedIncrementalData, context);
148
148
  }
149
149
  else {
150
150
  this._handleCompletedStreamItems(completedIncrementalData, context);
151
151
  }
152
152
  }
153
- _handleCompletedDeferredGroupedFieldSet(deferredGroupedFieldSetResult, context) {
154
- if (isNonReconcilableDeferredGroupedFieldSetResult(deferredGroupedFieldSetResult)) {
155
- for (const deferredFragmentRecord of deferredGroupedFieldSetResult
156
- .deferredGroupedFieldSetRecord.deferredFragmentRecords) {
153
+ _handleCompletedExecutionGroup(completedExecutionGroup, context) {
154
+ if (isFailedExecutionGroup(completedExecutionGroup)) {
155
+ for (const deferredFragmentRecord of completedExecutionGroup.pendingExecutionGroup
156
+ .deferredFragmentRecords) {
157
157
  const id = deferredFragmentRecord.id;
158
158
  if (!this._incrementalGraph.removeDeferredFragment(deferredFragmentRecord)) {
159
159
  // This can occur if multiple deferred grouped field sets error for a fragment.
@@ -164,7 +164,7 @@ class IncrementalPublisher {
164
164
  const incrementalEntry = {
165
165
  id,
166
166
  data: null,
167
- errors: deferredGroupedFieldSetResult.errors,
167
+ errors: completedExecutionGroup.errors,
168
168
  };
169
169
  if (this._context.sendPathAndLabelOnIncremental) {
170
170
  const { path, label } = deferredFragmentRecord;
@@ -179,14 +179,14 @@ class IncrementalPublisher {
179
179
  else {
180
180
  context.completed.push({
181
181
  id,
182
- errors: deferredGroupedFieldSetResult.errors,
182
+ errors: completedExecutionGroup.errors,
183
183
  });
184
184
  }
185
185
  }
186
186
  return;
187
187
  }
188
- this._incrementalGraph.addCompletedReconcilableDeferredGroupedFieldSet(deferredGroupedFieldSetResult);
189
- for (const deferredFragmentRecord of deferredGroupedFieldSetResult.deferredGroupedFieldSetRecord
188
+ this._incrementalGraph.addCompletedSuccessfulExecutionGroup(completedExecutionGroup);
189
+ for (const deferredFragmentRecord of completedExecutionGroup.pendingExecutionGroup
190
190
  .deferredFragmentRecords) {
191
191
  const completion = this._incrementalGraph.completeDeferredFragment(deferredFragmentRecord);
192
192
  if (completion === undefined) {
@@ -195,12 +195,12 @@ class IncrementalPublisher {
195
195
  const id = deferredFragmentRecord.id;
196
196
  invariant(id !== undefined);
197
197
  const incremental = context.incremental;
198
- const { newPending, reconcilableResults } = completion;
198
+ const { newPending, successfulExecutionGroups } = completion;
199
199
  context.pending.push(...this._pendingSourcesToResults(newPending));
200
- for (const reconcilableResult of reconcilableResults) {
201
- const { bestId, subPath } = this._getBestIdAndSubPath(id, deferredFragmentRecord, reconcilableResult);
200
+ for (const successfulExecutionGroup of successfulExecutionGroups) {
201
+ const { bestId, subPath } = this._getBestIdAndSubPath(id, deferredFragmentRecord, successfulExecutionGroup);
202
202
  const incrementalEntry = {
203
- ...reconcilableResult.result,
203
+ ...successfulExecutionGroup.result,
204
204
  id: bestId,
205
205
  };
206
206
  if (this._context.sendPathAndLabelOnIncremental) {
@@ -285,10 +285,10 @@ class IncrementalPublisher {
285
285
  }
286
286
  }
287
287
  }
288
- _getBestIdAndSubPath(initialId, initialDeferredFragmentRecord, deferredGroupedFieldSetResult) {
288
+ _getBestIdAndSubPath(initialId, initialDeferredFragmentRecord, completedExecutionGroup) {
289
289
  let maxLength = pathToArray(initialDeferredFragmentRecord.path).length;
290
290
  let bestId = initialId;
291
- for (const deferredFragmentRecord of deferredGroupedFieldSetResult.deferredGroupedFieldSetRecord
291
+ for (const deferredFragmentRecord of completedExecutionGroup.pendingExecutionGroup
292
292
  .deferredFragmentRecords) {
293
293
  if (deferredFragmentRecord === initialDeferredFragmentRecord) {
294
294
  continue;
@@ -306,7 +306,7 @@ class IncrementalPublisher {
306
306
  bestId = id;
307
307
  }
308
308
  }
309
- const subPath = deferredGroupedFieldSetResult.path.slice(maxLength);
309
+ const subPath = completedExecutionGroup.path.slice(maxLength);
310
310
  return {
311
311
  bestId,
312
312
  subPath: subPath.length > 0 ? subPath : undefined,
@@ -1,45 +1,19 @@
1
1
  import { AccumulatorMap } from './AccumulatorMap.js';
2
2
  import { getBySet } from './getBySet.js';
3
3
  import { isSameSet } from './isSameSet.js';
4
- export function buildFieldPlan(originalGroupedFieldSet, parentDeferUsages = new Set()) {
4
+ export function buildExecutionPlan(originalGroupedFieldSet, parentDeferUsages = new Set()) {
5
5
  const groupedFieldSet = new Map();
6
6
  const newGroupedFieldSets = new Map();
7
- const map = new Map();
8
7
  for (const [responseKey, fieldGroup] of originalGroupedFieldSet) {
9
- const deferUsageSet = new Set();
10
- let inOriginalResult = false;
11
- for (const fieldDetails of fieldGroup) {
12
- const deferUsage = fieldDetails.deferUsage;
13
- if (deferUsage === undefined) {
14
- inOriginalResult = true;
15
- continue;
16
- }
17
- deferUsageSet.add(deferUsage);
18
- }
19
- if (inOriginalResult) {
20
- deferUsageSet.clear();
21
- }
22
- else {
23
- deferUsageSet.forEach(deferUsage => {
24
- const ancestors = getAncestors(deferUsage);
25
- for (const ancestor of ancestors) {
26
- if (deferUsageSet.has(ancestor)) {
27
- deferUsageSet.delete(deferUsage);
28
- }
29
- }
30
- });
31
- }
32
- map.set(responseKey, { deferUsageSet, fieldGroup });
33
- }
34
- for (const [responseKey, { deferUsageSet, fieldGroup }] of map) {
35
- if (isSameSet(deferUsageSet, parentDeferUsages)) {
8
+ const filteredDeferUsageSet = getFilteredDeferUsageSet(fieldGroup);
9
+ if (isSameSet(filteredDeferUsageSet, parentDeferUsages)) {
36
10
  groupedFieldSet.set(responseKey, fieldGroup);
37
11
  continue;
38
12
  }
39
- let newGroupedFieldSet = getBySet(newGroupedFieldSets, deferUsageSet);
13
+ let newGroupedFieldSet = getBySet(newGroupedFieldSets, filteredDeferUsageSet);
40
14
  if (newGroupedFieldSet === undefined) {
41
15
  newGroupedFieldSet = new Map();
42
- newGroupedFieldSets.set(deferUsageSet, newGroupedFieldSet);
16
+ newGroupedFieldSets.set(filteredDeferUsageSet, newGroupedFieldSet);
43
17
  }
44
18
  newGroupedFieldSet.set(responseKey, fieldGroup);
45
19
  }
@@ -48,16 +22,29 @@ export function buildFieldPlan(originalGroupedFieldSet, parentDeferUsages = new
48
22
  newGroupedFieldSets,
49
23
  };
50
24
  }
51
- function getAncestors(deferUsage) {
52
- const ancestors = [];
53
- let parentDeferUsage = deferUsage.parentDeferUsage;
54
- while (parentDeferUsage !== undefined) {
55
- ancestors.unshift(parentDeferUsage);
56
- parentDeferUsage = parentDeferUsage.parentDeferUsage;
25
+ function getFilteredDeferUsageSet(fieldGroup) {
26
+ const filteredDeferUsageSet = new Set();
27
+ for (const fieldDetails of fieldGroup) {
28
+ const deferUsage = fieldDetails.deferUsage;
29
+ if (deferUsage === undefined) {
30
+ filteredDeferUsageSet.clear();
31
+ return filteredDeferUsageSet;
32
+ }
33
+ filteredDeferUsageSet.add(deferUsage);
34
+ }
35
+ for (const deferUsage of filteredDeferUsageSet) {
36
+ let parentDeferUsage = deferUsage.parentDeferUsage;
37
+ while (parentDeferUsage !== undefined) {
38
+ if (filteredDeferUsageSet.has(parentDeferUsage)) {
39
+ filteredDeferUsageSet.delete(deferUsage);
40
+ break;
41
+ }
42
+ parentDeferUsage = parentDeferUsage.parentDeferUsage;
43
+ }
57
44
  }
58
- return ancestors;
45
+ return filteredDeferUsageSet;
59
46
  }
60
- export function buildBranchingFieldPlan(originalGroupedFieldSet, parentDeferUsages = new Set()) {
47
+ export function buildBranchingExecutionPlan(originalGroupedFieldSet, parentDeferUsages = new Set()) {
61
48
  const groupedFieldSet = new AccumulatorMap();
62
49
  const newGroupedFieldSets = new Map();
63
50
  for (const [responseKey, fieldGroup] of originalGroupedFieldSet) {