grafast 1.0.0-rc.6 → 1.0.0-rc.7
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.
- package/dist/engine/LayerPlan.js +30 -3
- package/dist/engine/OperationPlan.js +3 -0
- package/dist/engine/distributor.js +3 -3
- package/dist/engine/executeBucket.js +26 -51
- package/dist/steps/_loadCommon.js +1 -1
- package/dist/steps/graphqlResolver.js +4 -2
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +2 -2
package/dist/engine/LayerPlan.js
CHANGED
|
@@ -16,12 +16,17 @@ const executeBucket_ts_1 = require("./executeBucket.js");
|
|
|
16
16
|
* If any of these flags exist on a value then it isn't the value we want to
|
|
17
17
|
* include for the combo step.
|
|
18
18
|
*/
|
|
19
|
-
const SKIP_FLAGS = constants_ts_1.FLAG_ERROR | constants_ts_1.FLAG_STOPPED | constants_ts_1.FLAG_POLY_SKIPPED | constants_ts_1.FLAG_INHIBITED;
|
|
19
|
+
const SKIP_FLAGS = constants_ts_1.FLAG_ERROR | constants_ts_1.FLAG_STOPPED | constants_ts_1.FLAG_POLY_SKIPPED | constants_ts_1.FLAG_INHIBITED | constants_ts_1.FLAG_NULL;
|
|
20
20
|
/**
|
|
21
21
|
* If any of these flags exist on the "$__typename" step, then the value
|
|
22
22
|
* should resolve to null
|
|
23
23
|
*/
|
|
24
24
|
const NO_TYPENAME_FLAGS = constants_ts_1.FLAG_ERROR | constants_ts_1.FLAG_STOPPED | constants_ts_1.FLAG_POLY_SKIPPED | constants_ts_1.FLAG_INHIBITED | constants_ts_1.FLAG_NULL;
|
|
25
|
+
/**
|
|
26
|
+
* Used to determine if we should copy the error. Should only be copied if it's
|
|
27
|
+
* NOT polymorphic skipped; so we check the result `=== FLAG_ERROR`
|
|
28
|
+
*/
|
|
29
|
+
const ERROR_OR_POLY_SKIPPED_FLAGS = constants_ts_1.FLAG_ERROR | constants_ts_1.FLAG_POLY_SKIPPED;
|
|
25
30
|
function hasParentLayerPlan(reason) {
|
|
26
31
|
return reason.type !== "root" && reason.type !== "combined";
|
|
27
32
|
}
|
|
@@ -298,6 +303,7 @@ class LayerPlan {
|
|
|
298
303
|
const polymorphicType = this.reason.type === "polymorphic" ? [] : null;
|
|
299
304
|
const iterators = this.reason.type === "mutationField" ? parentBucket.iterators : [];
|
|
300
305
|
const map = new Map();
|
|
306
|
+
let flagUnion = parentBucket.flagUnion;
|
|
301
307
|
const $parentSideEffect = this.parentSideEffectStep;
|
|
302
308
|
let parentSideEffectValue;
|
|
303
309
|
if ($parentSideEffect) {
|
|
@@ -476,6 +482,7 @@ class LayerPlan {
|
|
|
476
482
|
flags = flags | constants_ts_1.FLAG_NULL;
|
|
477
483
|
}
|
|
478
484
|
}
|
|
485
|
+
flagUnion |= flags;
|
|
479
486
|
ev._setResult(newIndex, val, flags);
|
|
480
487
|
polymorphicPathList[newIndex] =
|
|
481
488
|
parentBucket.polymorphicPathList[originalIndex];
|
|
@@ -640,7 +647,7 @@ class LayerPlan {
|
|
|
640
647
|
size,
|
|
641
648
|
store,
|
|
642
649
|
// PERF: not necessarily, if we don't copy the errors, we don't have the errors.
|
|
643
|
-
flagUnion
|
|
650
|
+
flagUnion,
|
|
644
651
|
polymorphicPathList,
|
|
645
652
|
polymorphicType,
|
|
646
653
|
iterators,
|
|
@@ -669,6 +676,8 @@ class LayerPlan {
|
|
|
669
676
|
return null;
|
|
670
677
|
}
|
|
671
678
|
}
|
|
679
|
+
// TODO: currently we copy nulls and errors through. Ideally we wouldn't,
|
|
680
|
+
// thereby shrinking the size of the bucket.
|
|
672
681
|
newCombinedBucket(finalParentBucket) {
|
|
673
682
|
const t = this.reason.type;
|
|
674
683
|
if (t !== "combined") {
|
|
@@ -753,6 +762,7 @@ class LayerPlan {
|
|
|
753
762
|
continue;
|
|
754
763
|
for (let originalIndex = 0; originalIndex < parentBucket.size; originalIndex++) {
|
|
755
764
|
const newIndex = originalIndex + offset;
|
|
765
|
+
let fallbackErrorSource = null;
|
|
756
766
|
if (sourceStepsByLayerPlanId[plp.id]) {
|
|
757
767
|
for (const stepId of sourceStepsByLayerPlanId[plp.id]) {
|
|
758
768
|
const sourceStore = parentBucket.store.get(stepId);
|
|
@@ -760,12 +770,29 @@ class LayerPlan {
|
|
|
760
770
|
const step = this.operationPlan.stepTracker.getStepById(stepId);
|
|
761
771
|
throw new Error(`GrafastInternalError<a48ca88c-e4b9-4a4f-9a38-846fa067f143>: missing source store for ${step} (${stepId}) in ${this}`);
|
|
762
772
|
}
|
|
763
|
-
|
|
773
|
+
const sourceFlags = sourceStore._flagsAt(originalIndex);
|
|
774
|
+
if ((sourceFlags & SKIP_FLAGS) === 0) {
|
|
764
775
|
ev._copyResult(newIndex, sourceStore, originalIndex);
|
|
776
|
+
fallbackErrorSource = null;
|
|
765
777
|
break;
|
|
766
778
|
}
|
|
779
|
+
else if (fallbackErrorSource === null &&
|
|
780
|
+
(sourceFlags & ERROR_OR_POLY_SKIPPED_FLAGS) === constants_ts_1.FLAG_ERROR) {
|
|
781
|
+
fallbackErrorSource = sourceStore;
|
|
782
|
+
} // If no matches, it retains `FLAG_NULL | FLAG_STOPPED` from above
|
|
767
783
|
}
|
|
768
784
|
}
|
|
785
|
+
if (fallbackErrorSource !== null) {
|
|
786
|
+
// No non-skipped source existed for this index; preserve the first
|
|
787
|
+
// available error instead of silently converting to stopped/null.
|
|
788
|
+
//
|
|
789
|
+
// Normally we'd do:
|
|
790
|
+
//
|
|
791
|
+
// ev._copyResult(newIndex, fallbackErrorSource, originalIndex);
|
|
792
|
+
//
|
|
793
|
+
// However, we want to add FLAG_STOPPED, so we do this manually:
|
|
794
|
+
ev._setResult(newIndex, fallbackErrorSource.at(originalIndex), fallbackErrorSource._flagsAt(originalIndex) | constants_ts_1.FLAG_STOPPED);
|
|
795
|
+
}
|
|
769
796
|
iterators[newIndex] = parentBucket.iterators[originalIndex];
|
|
770
797
|
}
|
|
771
798
|
offset += parentBucket.size;
|
|
@@ -1220,6 +1220,9 @@ class OperationPlan {
|
|
|
1220
1220
|
: (0, step_ts_1.stepHasToRecord)($original)
|
|
1221
1221
|
? (0, withGlobalLayerPlan_ts_1.withGlobalLayerPlan)(commonLayerPlan, polymorphicPaths, planningPath, null, $original.toRecord, $original)
|
|
1222
1222
|
: $original;
|
|
1223
|
+
// Combo layer plan filters nulls for us; since we're skipping that
|
|
1224
|
+
// we need to explicitly inhibit nulls
|
|
1225
|
+
commonStep = (0, withGlobalLayerPlan_ts_1.withGlobalLayerPlan)(commonLayerPlan, polymorphicPaths, planningPath, null, index_ts_1.inhibitOnNull, null, commonStep);
|
|
1223
1226
|
for (const detailsRecord of detailsRecordList) {
|
|
1224
1227
|
detailsRecord.layerPlan = commonLayerPlan;
|
|
1225
1228
|
const polymorphicPaths = detailsRecord.polymorphicPaths;
|
|
@@ -147,7 +147,7 @@ function distributor(sourceIterable, dependentSteps, abortSignal, distributorOpt
|
|
|
147
147
|
let advanced = false;
|
|
148
148
|
while (smallest >= lowWaterMark) {
|
|
149
149
|
advanced = true;
|
|
150
|
-
buffer.shift();
|
|
150
|
+
void buffer.shift();
|
|
151
151
|
lowWaterMark++;
|
|
152
152
|
}
|
|
153
153
|
// Announce that the lowWaterMark advanced
|
|
@@ -342,14 +342,14 @@ function distributor(sourceIterable, dependentSteps, abortSignal, distributorOpt
|
|
|
342
342
|
const stepIndex = getStepIndex(stepId);
|
|
343
343
|
if (!hasIterator[stepIndex]) {
|
|
344
344
|
hasIterator[stepIndex] = true;
|
|
345
|
-
stop(stepIndex);
|
|
345
|
+
void stop(stepIndex);
|
|
346
346
|
}
|
|
347
347
|
},
|
|
348
348
|
};
|
|
349
349
|
abortSignal.addEventListener("abort", () => {
|
|
350
350
|
for (let stepIndex = 0, l = dependentSteps.length; stepIndex < l; stepIndex++) {
|
|
351
351
|
hasIterator[stepIndex] = true;
|
|
352
|
-
stop(stepIndex, undefined, false);
|
|
352
|
+
void stop(stepIndex, undefined, false);
|
|
353
353
|
}
|
|
354
354
|
maybeAdvanceLowWaterMark();
|
|
355
355
|
});
|
|
@@ -181,9 +181,7 @@ function executeBucket(bucket, requestContext) {
|
|
|
181
181
|
// **DO NOT THROW, DO NOT ALLOW AN ERROR TO BE RAISED!**
|
|
182
182
|
// **USE DEFENSIVE PROGRAMMING HERE!**
|
|
183
183
|
/** PROMISES ADDED HERE MUST NOT REJECT */
|
|
184
|
-
let promises;
|
|
185
|
-
let pendingPromises;
|
|
186
|
-
let pendingPromiseIndexes;
|
|
184
|
+
let promises = undefined;
|
|
187
185
|
// TODO: it seems that if this throws an error it results in a permanent
|
|
188
186
|
// hang of defers? In the mean time... Don't throw any errors here!
|
|
189
187
|
const success = (finishedStep, bucket, resultIndex, rawValue, flags) => {
|
|
@@ -234,8 +232,9 @@ function executeBucket(bucket, requestContext) {
|
|
|
234
232
|
}
|
|
235
233
|
replacement[i] = null;
|
|
236
234
|
const index = i;
|
|
235
|
+
// Must not reject
|
|
237
236
|
const promise = item.then((v) => void (replacement[index] = v), (e) => void (replacement[index] = (0, error_ts_1.flagError)(e)));
|
|
238
|
-
if (
|
|
237
|
+
if (promises === undefined) {
|
|
239
238
|
promises = [promise];
|
|
240
239
|
}
|
|
241
240
|
else {
|
|
@@ -343,7 +342,7 @@ function executeBucket(bucket, requestContext) {
|
|
|
343
342
|
bucket.setResult(finishedStep, resultIndex, e, flags | constants_ts_1.FLAG_ERROR);
|
|
344
343
|
}
|
|
345
344
|
})();
|
|
346
|
-
if (
|
|
345
|
+
if (promises === undefined) {
|
|
347
346
|
promises = [promise];
|
|
348
347
|
}
|
|
349
348
|
else {
|
|
@@ -365,56 +364,26 @@ function executeBucket(bucket, requestContext) {
|
|
|
365
364
|
const count = step._isUnary ? 1 : size;
|
|
366
365
|
for (let dataIndex = 0; dataIndex < count; dataIndex++) {
|
|
367
366
|
const val = results[dataIndex];
|
|
367
|
+
const valFlags = flags[dataIndex];
|
|
368
|
+
if (valFlags == null) {
|
|
369
|
+
throw new Error(`GraphileInternalError<75df71bb-0f76-4a98-9664-9167d502296a>: result for ${step} has no flag at index ${dataIndex} (value = ${(0, inspect_ts_1.inspect)(val)})`);
|
|
370
|
+
}
|
|
368
371
|
if (step.isSyncAndSafe || !(0, utils_ts_1.isPromiseLike)(val)) {
|
|
369
|
-
|
|
370
|
-
throw new Error(`GraphileInternalError<75df71bb-0f76-4a98-9664-9167d502296a>: result for ${step} has no flag at index ${dataIndex} (value = ${(0, inspect_ts_1.inspect)(val)})`);
|
|
371
|
-
}
|
|
372
|
-
success(step, bucket, dataIndex, val, flags[dataIndex]);
|
|
372
|
+
success(step, bucket, dataIndex, val, valFlags);
|
|
373
373
|
}
|
|
374
374
|
else {
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
375
|
+
// Must not reject!
|
|
376
|
+
const valSuccess = val.then((val) => success(step, bucket, dataIndex, val, valFlags), (error) => bucket.setResult(step, dataIndex, error, constants_ts_1.FLAG_ERROR));
|
|
377
|
+
if (promises === undefined) {
|
|
378
|
+
promises = [valSuccess];
|
|
378
379
|
}
|
|
379
380
|
else {
|
|
380
|
-
|
|
381
|
-
pendingPromiseIndexes.push({ s: allStepsIndex, i: dataIndex });
|
|
381
|
+
promises.push(valSuccess);
|
|
382
382
|
}
|
|
383
383
|
}
|
|
384
384
|
}
|
|
385
385
|
}
|
|
386
|
-
|
|
387
|
-
return Promise.allSettled(pendingPromises)
|
|
388
|
-
.then((resultSettledResult) => {
|
|
389
|
-
for (let i = 0, pendingPromisesLength = resultSettledResult.length; i < pendingPromisesLength; i++) {
|
|
390
|
-
const settledResult = resultSettledResult[i];
|
|
391
|
-
const { s: allStepsIndex, i: dataIndex } = pendingPromiseIndexes[i];
|
|
392
|
-
const finishedStep = _allSteps[allStepsIndex];
|
|
393
|
-
if (settledResult.status === "fulfilled") {
|
|
394
|
-
success(finishedStep, bucket, dataIndex, settledResult.value, constants_ts_1.NO_FLAGS);
|
|
395
|
-
}
|
|
396
|
-
else {
|
|
397
|
-
const error = settledResult.reason;
|
|
398
|
-
bucket.setResult(finishedStep, dataIndex, error, constants_ts_1.FLAG_ERROR);
|
|
399
|
-
}
|
|
400
|
-
}
|
|
401
|
-
return promises ? Promise.all(promises) : undefined;
|
|
402
|
-
})
|
|
403
|
-
.then(null, (e) => {
|
|
404
|
-
// THIS SHOULD NEVER HAPPEN!
|
|
405
|
-
console.error(`GrafastInternalError<1e9731b4-005e-4b0e-bc61-43baa62e6444>: this error should never occur! Please file an issue against grafast. Details: ${e}`);
|
|
406
|
-
bucket.flagUnion |= constants_ts_1.FLAG_ERROR;
|
|
407
|
-
for (let i = 0, pendingPromisesLength = pendingPromises.length; i < pendingPromisesLength; i++) {
|
|
408
|
-
const { s: allStepsIndex, i: dataIndex } = pendingPromiseIndexes[i];
|
|
409
|
-
const finishedStep = _allSteps[allStepsIndex];
|
|
410
|
-
const error = new Error(`GrafastInternalError<1e9731b4-005e-4b0e-bc61-43baa62e6444>: error occurred whilst performing completedStep(${finishedStep.id})`);
|
|
411
|
-
bucket.setResult(finishedStep, dataIndex, error, constants_ts_1.FLAG_ERROR);
|
|
412
|
-
}
|
|
413
|
-
});
|
|
414
|
-
}
|
|
415
|
-
else {
|
|
416
|
-
return promises ? Promise.all(promises) : undefined;
|
|
417
|
-
}
|
|
386
|
+
return promises === undefined ? undefined : Promise.all(promises);
|
|
418
387
|
};
|
|
419
388
|
const runSyncSteps = () => {
|
|
420
389
|
const executedLength = resultList.length;
|
|
@@ -1046,14 +1015,22 @@ function markLayerPlanAsDone(requestContext, sharedState, layerPlan, bucket) {
|
|
|
1046
1015
|
if (!allParentLayerPlansAreReady) {
|
|
1047
1016
|
// The last parent layer plan to complete will handle it.
|
|
1048
1017
|
// Make sure we're retained so it can use our data!
|
|
1049
|
-
//
|
|
1018
|
+
// Released below.
|
|
1050
1019
|
if (bucket != null) {
|
|
1051
1020
|
bucket.sharedState.retain(bucket);
|
|
1052
1021
|
}
|
|
1053
|
-
// TODO: MAKE SURE CANCELLED BUCKETS ARE HANDLED!
|
|
1054
1022
|
continue loop;
|
|
1055
1023
|
}
|
|
1056
1024
|
const childBucket = childLayerPlan.newCombinedBucket({ sharedState });
|
|
1025
|
+
// Every parent except the final parent was retained while waiting for all
|
|
1026
|
+
// parents to complete; release those temporary retains now.
|
|
1027
|
+
for (const plp of childLayerPlan.reason.parentLayerPlans) {
|
|
1028
|
+
if (plp === layerPlan)
|
|
1029
|
+
continue; // Was never retained
|
|
1030
|
+
const otherBucket = sharedState._retainedBuckets.get(plp.id);
|
|
1031
|
+
if (otherBucket !== undefined)
|
|
1032
|
+
sharedState.release(otherBucket);
|
|
1033
|
+
}
|
|
1057
1034
|
if (childBucket !== null) {
|
|
1058
1035
|
// Execute
|
|
1059
1036
|
const result = executeBucket(childBucket, requestContext);
|
|
@@ -1174,9 +1151,7 @@ function newBucket(parent, spec) {
|
|
|
1174
1151
|
if (index >= size) {
|
|
1175
1152
|
throw new Error(`GrafastInternalError<9465db89-cc9d-415c-97e7-57bb19ddebe0>: attempt to write to out of bounds index ${index} for bucket of size ${size} for step ${step}`);
|
|
1176
1153
|
}
|
|
1177
|
-
|
|
1178
|
-
this.flagUnion |= flags;
|
|
1179
|
-
}
|
|
1154
|
+
this.flagUnion |= flags;
|
|
1180
1155
|
if (step._isUnary) {
|
|
1181
1156
|
if (dev_ts_1.isDev && store.has(stepId)) {
|
|
1182
1157
|
const ev = store.get(stepId);
|
|
@@ -171,7 +171,7 @@ function executeLoad(details, sharedDepId, paramDepIdByKey, baseLoadInfo, load)
|
|
|
171
171
|
(0, exports.nextTick)(() => {
|
|
172
172
|
// Don't allow adding anything else to the batch
|
|
173
173
|
meta.loadBatchesByLoad.delete(load);
|
|
174
|
-
executeBatches(loadBatches, loadInfo, load);
|
|
174
|
+
void executeBatches(loadBatches, loadInfo, load);
|
|
175
175
|
});
|
|
176
176
|
}
|
|
177
177
|
return (async () => {
|
|
@@ -66,10 +66,10 @@ class GraphQLResolverStep extends step_ts_1.UnbatchedStep {
|
|
|
66
66
|
}
|
|
67
67
|
else {
|
|
68
68
|
if (this.isNotRoot) {
|
|
69
|
-
return
|
|
69
|
+
return (0, index_ts_1.flagError)(new Error(`Invalid non-root subscribe`));
|
|
70
70
|
}
|
|
71
71
|
if (this.subscriber == null) {
|
|
72
|
-
return
|
|
72
|
+
return (0, index_ts_1.flagError)(new Error(`Cannot subscribe to field`));
|
|
73
73
|
}
|
|
74
74
|
const resolveInfo = Object.assign(Object.create(this.resolveInfoBase), {
|
|
75
75
|
// ENHANCE: add support for path
|
|
@@ -119,6 +119,8 @@ class GraphQLResolveTypeStep extends step_ts_1.Step {
|
|
|
119
119
|
* resolution part.
|
|
120
120
|
*/
|
|
121
121
|
figureOutTheTypeOf(data, context, resolveInfo) {
|
|
122
|
+
if (data == null)
|
|
123
|
+
return data;
|
|
122
124
|
const abstractType = this.abstractType;
|
|
123
125
|
if (abstractType.resolveType != null) {
|
|
124
126
|
return abstractType.resolveType(data, context, resolveInfo, abstractType);
|
package/dist/version.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const version = "1.0.0-rc.
|
|
1
|
+
export declare const version = "1.0.0-rc.7";
|
|
2
2
|
//# sourceMappingURL=version.d.ts.map
|
package/dist/version.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "grafast",
|
|
3
|
-
"version": "1.0.0-rc.
|
|
3
|
+
"version": "1.0.0-rc.7",
|
|
4
4
|
"description": "Cutting edge GraphQL planning and execution engine",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
"chalk": "^4.1.2",
|
|
60
60
|
"debug": "^4.4.3",
|
|
61
61
|
"eventemitter3": "^5.0.1",
|
|
62
|
-
"graphile-config": "^1.0.0-rc.
|
|
62
|
+
"graphile-config": "^1.0.0-rc.5",
|
|
63
63
|
"graphql": "^16.9.0",
|
|
64
64
|
"iterall": "^1.3.0",
|
|
65
65
|
"tslib": "^2.8.1"
|