1
1
import { BoxedPromiseOrValue } from '../jsutils/BoxedPromiseOrValue.js' ;
2
2
import { invariant } from '../jsutils/invariant.js' ;
3
3
import { isPromise } from '../jsutils/isPromise.js' ;
4
+ import type { Path } from '../jsutils/Path.js' ;
4
5
import { promiseWithResolvers } from '../jsutils/promiseWithResolvers.js' ;
5
6
6
7
import type { GraphQLError } from '../error/GraphQLError.js' ;
7
8
9
+ import type { DeferUsage } from './collectFields.js' ;
8
10
import type {
9
11
DeferredFragmentRecord ,
10
12
DeliveryGroup ,
13
+ } from './DeferredFragments.js' ;
14
+ import {
15
+ DeferredFragmentFactory ,
16
+ isDeferredFragmentRecord ,
17
+ } from './DeferredFragments.js' ;
18
+ import type {
11
19
IncrementalDataRecord ,
12
20
IncrementalDataRecordResult ,
13
21
PendingExecutionGroup ,
14
22
StreamItemRecord ,
15
23
StreamRecord ,
16
24
SuccessfulExecutionGroup ,
17
25
} from './types.js' ;
18
- import { isDeferredFragmentRecord , isPendingExecutionGroup } from './types.js' ;
26
+ import { isPendingExecutionGroup } from './types.js' ;
19
27
20
28
/**
21
29
* @internal
22
30
*/
23
31
export class IncrementalGraph {
24
32
private _rootNodes : Set < DeliveryGroup > ;
25
-
33
+ private _deferredFragmentFactory : DeferredFragmentFactory ;
26
34
private _completedQueue : Array < IncrementalDataRecordResult > ;
27
35
private _nextQueue : Array <
28
36
( iterable : Iterable < IncrementalDataRecordResult > | undefined ) => void
29
37
> ;
30
38
31
39
constructor ( ) {
40
+ this . _deferredFragmentFactory = new DeferredFragmentFactory ( ) ;
32
41
this . _rootNodes = new Set ( ) ;
33
42
this . _completedQueue = [ ] ;
34
43
this . _nextQueue = [ ] ;
@@ -51,11 +60,15 @@ export class IncrementalGraph {
51
60
) : void {
52
61
const { pendingExecutionGroup, incrementalDataRecords } =
53
62
successfulExecutionGroup ;
63
+ const { deferUsages, path } = pendingExecutionGroup ;
54
64
55
- const deferredFragmentRecords =
56
- pendingExecutionGroup . deferredFragmentRecords ;
57
-
58
- for ( const deferredFragmentRecord of deferredFragmentRecords ) {
65
+ const deferredFragmentRecords : Array < DeferredFragmentRecord > = [ ] ;
66
+ for ( const deferUsage of deferUsages ) {
67
+ const deferredFragmentRecord = this . _deferredFragmentFactory . get (
68
+ deferUsage ,
69
+ path ,
70
+ ) ;
71
+ deferredFragmentRecords . push ( deferredFragmentRecord ) ;
59
72
const { pendingExecutionGroups, successfulExecutionGroups } =
60
73
deferredFragmentRecord ;
61
74
pendingExecutionGroups . delete ( pendingExecutionGroup ) ;
@@ -70,6 +83,26 @@ export class IncrementalGraph {
70
83
}
71
84
}
72
85
86
+ getDeepestDeferredFragmentAtRoot (
87
+ initialDeferUsage : DeferUsage ,
88
+ deferUsages : ReadonlySet < DeferUsage > ,
89
+ path : Path | undefined ,
90
+ ) : DeferredFragmentRecord {
91
+ let bestDeferUsage = initialDeferUsage ;
92
+ let maxDepth = initialDeferUsage . depth ;
93
+ for ( const deferUsage of deferUsages ) {
94
+ if ( deferUsage === initialDeferUsage ) {
95
+ continue ;
96
+ }
97
+ const depth = deferUsage . depth ;
98
+ if ( depth > maxDepth ) {
99
+ maxDepth = depth ;
100
+ bestDeferUsage = deferUsage ;
101
+ }
102
+ }
103
+ return this . _deferredFragmentFactory . get ( bestDeferUsage , path ) ;
104
+ }
105
+
73
106
* currentCompletedBatch ( ) : Generator < IncrementalDataRecordResult > {
74
107
let completed ;
75
108
while ( ( completed = this . _completedQueue . shift ( ) ) !== undefined ) {
@@ -102,12 +135,20 @@ export class IncrementalGraph {
102
135
return this . _rootNodes . size > 0 ;
103
136
}
104
137
105
- completeDeferredFragment ( deferredFragmentRecord : DeferredFragmentRecord ) :
138
+ completeDeferredFragment (
139
+ deferUsage : DeferUsage ,
140
+ path : Path | undefined ,
141
+ ) :
106
142
| {
143
+ deferredFragmentRecord : DeferredFragmentRecord ;
107
144
newRootNodes : ReadonlyArray < DeliveryGroup > ;
108
145
successfulExecutionGroups : ReadonlyArray < SuccessfulExecutionGroup > ;
109
146
}
110
147
| undefined {
148
+ const deferredFragmentRecord = this . _deferredFragmentFactory . get (
149
+ deferUsage ,
150
+ path ,
151
+ ) ;
111
152
if (
112
153
! this . _rootNodes . has ( deferredFragmentRecord ) ||
113
154
deferredFragmentRecord . pendingExecutionGroups . size > 0
@@ -119,8 +160,13 @@ export class IncrementalGraph {
119
160
) ;
120
161
this . _rootNodes . delete ( deferredFragmentRecord ) ;
121
162
for ( const successfulExecutionGroup of successfulExecutionGroups ) {
122
- for ( const otherDeferredFragmentRecord of successfulExecutionGroup
123
- . pendingExecutionGroup . deferredFragmentRecords ) {
163
+ const { deferUsages, path : resultPath } =
164
+ successfulExecutionGroup . pendingExecutionGroup ;
165
+ for ( const otherDeferUsage of deferUsages ) {
166
+ const otherDeferredFragmentRecord = this . _deferredFragmentFactory . get (
167
+ otherDeferUsage ,
168
+ resultPath ,
169
+ ) ;
124
170
otherDeferredFragmentRecord . successfulExecutionGroups . delete (
125
171
successfulExecutionGroup ,
126
172
) ;
@@ -129,17 +175,22 @@ export class IncrementalGraph {
129
175
const newRootNodes = this . _promoteNonEmptyToRoot (
130
176
deferredFragmentRecord . children ,
131
177
) ;
132
- return { newRootNodes, successfulExecutionGroups } ;
178
+ return { deferredFragmentRecord , newRootNodes, successfulExecutionGroups } ;
133
179
}
134
180
135
181
removeDeferredFragment (
136
- deferredFragmentRecord : DeferredFragmentRecord ,
137
- ) : boolean {
182
+ deferUsage : DeferUsage ,
183
+ path : Path | undefined ,
184
+ ) : DeferredFragmentRecord | undefined {
185
+ const deferredFragmentRecord = this . _deferredFragmentFactory . get (
186
+ deferUsage ,
187
+ path ,
188
+ ) ;
138
189
if ( ! this . _rootNodes . has ( deferredFragmentRecord ) ) {
139
- return false ;
190
+ return ;
140
191
}
141
192
this . _rootNodes . delete ( deferredFragmentRecord ) ;
142
- return true ;
193
+ return deferredFragmentRecord ;
143
194
}
144
195
145
196
removeStream ( streamRecord : StreamRecord ) : void {
@@ -153,7 +204,12 @@ export class IncrementalGraph {
153
204
) : void {
154
205
for ( const incrementalDataRecord of incrementalDataRecords ) {
155
206
if ( isPendingExecutionGroup ( incrementalDataRecord ) ) {
156
- for ( const deferredFragmentRecord of incrementalDataRecord . deferredFragmentRecords ) {
207
+ const { deferUsages, path } = incrementalDataRecord ;
208
+ for ( const deferUsage of deferUsages ) {
209
+ const deferredFragmentRecord = this . _deferredFragmentFactory . get (
210
+ deferUsage ,
211
+ path ,
212
+ ) ;
157
213
this . _addDeferredFragment (
158
214
deferredFragmentRecord ,
159
215
initialResultChildren ,
@@ -210,9 +266,17 @@ export class IncrementalGraph {
210
266
private _completesRootNode (
211
267
pendingExecutionGroup : PendingExecutionGroup ,
212
268
) : boolean {
213
- return pendingExecutionGroup . deferredFragmentRecords . some (
214
- ( deferredFragmentRecord ) => this . _rootNodes . has ( deferredFragmentRecord ) ,
215
- ) ;
269
+ const { deferUsages, path } = pendingExecutionGroup ;
270
+ for ( const deferUsage of deferUsages ) {
271
+ const deferredFragmentRecord = this . _deferredFragmentFactory . get (
272
+ deferUsage ,
273
+ path ,
274
+ ) ;
275
+ if ( this . _rootNodes . has ( deferredFragmentRecord ) ) {
276
+ return true ;
277
+ }
278
+ }
279
+ return false ;
216
280
}
217
281
218
282
private _addDeferredFragment (
@@ -222,12 +286,16 @@ export class IncrementalGraph {
222
286
if ( this . _rootNodes . has ( deferredFragmentRecord ) ) {
223
287
return ;
224
288
}
225
- const parent = deferredFragmentRecord . parent ;
226
- if ( parent === undefined ) {
289
+ const parentDeferUsage = deferredFragmentRecord . parentDeferUsage ;
290
+ if ( parentDeferUsage === undefined ) {
227
291
invariant ( initialResultChildren !== undefined ) ;
228
292
initialResultChildren . add ( deferredFragmentRecord ) ;
229
293
return ;
230
294
}
295
+ const parent = this . _deferredFragmentFactory . get (
296
+ parentDeferUsage ,
297
+ deferredFragmentRecord . path ,
298
+ ) ;
231
299
parent . children . add ( deferredFragmentRecord ) ;
232
300
this . _addDeferredFragment ( parent , initialResultChildren ) ;
233
301
}
0 commit comments