@@ -134,21 +134,22 @@ ExecuteQuery(query, schema, variableValues, initialValue):
134
134
135
135
- Let {subsequentPayloads} be an empty list.
136
136
- Initialize {branches} to the empty set.
137
+ - Initialize {streams} to the empty set.
137
138
- Let {queryType} be the root Query type in {schema}.
138
139
- Assert: {queryType} is an Object type.
139
140
- Let {selectionSet} be the top level Selection Set in {query}.
140
141
- Let {groupedFieldSet} and {newDeferDepth} be the result of
141
142
{CollectRootFields(queryType, selectionSet, variableValues)}.
142
143
- Let {data} be the result of running {ExecuteGroupedFieldSet(groupedFieldSet,
143
- queryType, initialValue, variableValues, subsequentPayloads, branches)}
144
- _ normally_ (allowing parallelization).
144
+ queryType, initialValue, variableValues, subsequentPayloads, branches,
145
+ streams)} _ normally_ (allowing parallelization).
145
146
- Let {errors} be the list of all _ field error_ raised while executing the
146
147
selection set.
147
148
- If {newDeferDepth} is defined and {ShouldBranch(branches, groupedFieldSet,
148
149
path)} is {true}:
149
150
- Call {ExecuteDeferredFragment(objectType, objectValue, groupedFieldSet,
150
151
path, newDeferDepth, variableValues, asyncRecord, subsequentPayloads,
151
- branches)}
152
+ branches, streams )}
152
153
- If {subsequentPayloads} is empty:
153
154
- Return an unordered map containing {data} and {errors}.
154
155
- If {subsequentPayloads} is not empty:
@@ -177,21 +178,22 @@ ExecuteMutation(mutation, schema, variableValues, initialValue):
177
178
178
179
- Let {subsequentPayloads} be an empty list.
179
180
- Initialize {branches} to the empty set.
181
+ - Initialize {streams} to the empty set.
180
182
- Let {mutationType} be the root Mutation type in {schema}.
181
183
- Assert: {mutationType} is an Object type.
182
184
- Let {selectionSet} be the top level Selection Set in {mutation}.
183
185
- Let {groupedFieldSet} and {newDeferDepth} be the result of
184
186
{CollectRootFields(queryType, selectionSet, variableValues)}.
185
187
- Let {data} be the result of running {ExecuteGroupedFieldSet(groupedFieldSet,
186
- mutationType, initialValue, variableValues, subsequentPayloads, branches)}
187
- _ serially_ .
188
+ mutationType, initialValue, variableValues, subsequentPayloads, branches,
189
+ streams)} _ serially_ .
188
190
- Let {errors} be the list of all _ field error_ raised while executing the
189
191
selection set.
190
192
- If {newDeferDepth} is defined and {ShouldBranch(branches, groupedFieldSet,
191
193
path)} is {true}:
192
194
- Call {ExecuteDeferredFragment(objectType, objectValue,
193
195
deferredGroupFieldSet, path, newDeferDepth, variableValues, asyncRecord,
194
- subsequentPayloads, branches)}
196
+ subsequentPayloads, branches, streams )}
195
197
- If {subsequentPayloads} is empty:
196
198
- Return an unordered map containing {data} and {errors}.
197
199
- If {subsequentPayloads} is not empty:
@@ -429,7 +431,7 @@ Each represented field in the grouped field set produces an entry into a
429
431
response map.
430
432
431
433
ExecuteGroupedFieldSet(groupedFieldSet, objectType, objectValue, variableValues,
432
- path, subsequentPayloads, branches, asyncRecord):
434
+ path, subsequentPayloads, branches, streams, asyncRecord):
433
435
434
436
- If {path} is not provided, initialize it to an empty list, unique for this
435
437
execution.
@@ -445,7 +447,7 @@ path, subsequentPayloads, branches, asyncRecord):
445
447
- If {fieldType} is defined:
446
448
- If {ShouldExecute(fieldGroup, asyncRecord)} is {true}:
447
449
- Let {responseValue} be {ExecuteField(objectType, objectValue, fieldType,
448
- fieldGroup, variableValues, path, subsequentPayloads, branches,
450
+ fieldGroup, variableValues, path, subsequentPayloads, branches, streams,
449
451
asyncRecord)}.
450
452
- Set {responseValue} as the value for {responseKey} in {resultMap}.
451
453
- Return {resultMap}.
@@ -807,7 +809,8 @@ All Async Payload Records are structures containing:
807
809
#### Execute Deferred Fragment
808
810
809
811
ExecuteDeferredFragment(objectType, objectValue, groupedFieldSet, path,
810
- deferDepth, variableValues, parentRecord, subsequentPayloads, branches):
812
+ deferDepth, variableValues, parentRecord, subsequentPayloads, branches,
813
+ streams):
811
814
812
815
- Let {deferRecord} be an async payload record created from {path} and
813
816
{deferDepth}.
@@ -825,7 +828,7 @@ deferDepth, variableValues, parentRecord, subsequentPayloads, branches):
825
828
- If {fieldType} is defined:
826
829
- Let {responseValue} be {ExecuteField(objectType, objectValue, fieldType,
827
830
fieldGroup, variableValues, path, subsequentPayloads, asyncRecord,
828
- branches)}.
831
+ branches, streams )}.
829
832
- Set {responseValue} as the value for {responseKey} in {resultMap}.
830
833
- Append any encountered field errors to {errors}.
831
834
- If {parentRecord} is defined:
@@ -890,7 +893,7 @@ finally completes that value either by recursively executing another selection
890
893
set or coercing a scalar value.
891
894
892
895
ExecuteField(objectType, objectValue, fieldType, fieldGroup, variableValues,
893
- path, subsequentPayloads, branches, asyncRecord):
896
+ path, subsequentPayloads, branches, streams, asyncRecord):
894
897
895
898
- Let {taggedField} be the value of the first entry in {fieldGroup}.
896
899
- Let {field} be the corresponding entry within {taggedField}.
@@ -903,7 +906,7 @@ path, subsequentPayloads, branches, asyncRecord):
903
906
argumentValues)}.
904
907
- Let {result} be the result of calling {CompleteValue(fieldType, fieldGroup,
905
908
resolvedValue, variableValues, fieldPath, subsequentPayloads, branches,
906
- asyncRecord)}.
909
+ streams, asyncRecord)}.
907
910
- Return {result}.
908
911
909
912
### Coercing Field Arguments
@@ -1007,7 +1010,7 @@ yielded items satisfies `initialCount` specified on the `@stream` directive.
1007
1010
#### Execute Stream Field
1008
1011
1009
1012
ExecuteStreamField(iterator, index, fieldGroup, innerType, path, deferDepth,
1010
- parentRecord, variableValues, subsequentPayloads, branches):
1013
+ parentRecord, variableValues, subsequentPayloads, branches, streams ):
1011
1014
1012
1015
- If {parentRecord} is defined:
1013
1016
- Let {deferDepth} be equal to the corresponding entry on {asyncRecord}.
@@ -1028,12 +1031,12 @@ parentRecord, variableValues, subsequentPayloads, branches):
1028
1031
- Otherwise:
1029
1032
- Let {item} be the item retrieved from {iterator}.
1030
1033
- Let {data} be the result of calling {CompleteValue(innerType, fieldGroup,
1031
- item, variableValues, itemPath, subsequentPayloads, branches,
1034
+ item, variableValues, itemPath, subsequentPayloads, branches, streams,
1032
1035
parentRecord)}.
1033
1036
- Append any encountered field errors to {errors}.
1034
1037
- Increment {index}.
1035
1038
- Call {ExecuteStreamField(iterator, index, fieldGroup, innerType, path,
1036
- streamRecord, variableValues, subsequentPayloads, branches)}.
1039
+ streamRecord, variableValues, subsequentPayloads, branches, streams )}.
1037
1040
- If a field error was raised, causing a {null} to be propagated to {data},
1038
1041
and {innerType} is a Non-Nullable type:
1039
1042
- Add an entry to {payload} named ` items ` with the value {null}.
@@ -1050,7 +1053,7 @@ parentRecord, variableValues, subsequentPayloads, branches):
1050
1053
- Append {streamRecord} to {subsequentPayloads}.
1051
1054
1052
1055
CompleteValue(fieldType, fieldGroup, result, variableValues, path,
1053
- subsequentPayloads, asyncRecord, branches):
1056
+ subsequentPayloads, asyncRecord, branches, streams ):
1054
1057
1055
1058
- If the {fieldType} is a Non-Null type:
1056
1059
- Let {innerType} be the inner type of {fieldType}.
@@ -1080,8 +1083,9 @@ subsequentPayloads, asyncRecord, branches):
1080
1083
- While {result} is not closed:
1081
1084
- If {streamDirective} is defined and {index} is greater than or equal to
1082
1085
{initialCount}:
1083
- - Call {ExecuteStreamField(iterator, index, fieldGroup, innerType, path,
1084
- asyncRecord, subsequentPayloads, branches)}.
1086
+ - If {ShouldStream(streams, fieldGroup)}:
1087
+ - Call {ExecuteStreamField(iterator, index, fieldGroup, innerType, path,
1088
+ asyncRecord, subsequentPayloads, branches, streams)}.
1085
1089
- Return {items}.
1086
1090
- Otherwise:
1087
1091
- Wait for the next item from {result} via the {iterator}.
@@ -1091,7 +1095,7 @@ subsequentPayloads, asyncRecord, branches):
1091
1095
{index} appended.
1092
1096
- Let {resolvedItem} be the result of calling {CompleteValue(innerType,
1093
1097
fieldGroup, resultItem, variableValues, itemPath, subsequentPayloads,
1094
- branches, asyncRecord)}.
1098
+ branches, streams, asyncRecord)}.
1095
1099
- Append {resolvedItem} to {items}.
1096
1100
- Increment {index}.
1097
1101
- Return {items}.
@@ -1107,12 +1111,12 @@ subsequentPayloads, asyncRecord, branches):
1107
1111
- Let {resultMap} be the result of evaluating
1108
1112
{ExecuteGroupedFieldSet(groupedSubfieldSet, deferredGroupedSubfieldsList
1109
1113
objectType, result, variableValues, path, subsequentPayloads, branches,
1110
- asyncRecord)} _ normally_ (allowing for parallelization).
1114
+ streams, asyncRecord)} _ normally_ (allowing for parallelization).
1111
1115
- If {newDeferDepth} is defined and {ShouldBranch(branches, groupedFieldSet,
1112
1116
path)} is {true}:
1113
1117
- Call {ExecuteDeferredFragment(objectType, objectValue, groupedFieldSet,
1114
1118
path, newDeferDepth, variableValues, asyncRecord, subsequentPayloads,
1115
- branches)},
1119
+ branches, streams )},
1116
1120
- Return {resultMap}.
1117
1121
1118
1122
ShouldBranch(branches, path):
@@ -1121,6 +1125,12 @@ ShouldBranch(branches, path):
1121
1125
- Add {path} to {branches}.
1122
1126
- Return {true}.
1123
1127
1128
+ ShouldStream(streams, path):
1129
+
1130
+ - If {streams} contains {path}, return {false}.
1131
+ - Add {path} to {streams}.
1132
+ - Return {true}.
1133
+
1124
1134
ShouldExecute(fieldGroup, asyncPayloadRecord):
1125
1135
1126
1136
- Let {hasDepth} equal {false}.
0 commit comments