grafast 0.1.1-beta.19 → 0.1.1-beta.20
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/OperationPlan.d.ts +5 -4
- package/dist/engine/OperationPlan.js +19 -24
- package/dist/establishOperationPlan.js +55 -39
- package/dist/inspect.js +1 -1
- package/dist/interfaces.d.ts +22 -8
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { FragmentDefinitionNode, GraphQLFieldMap, GraphQLObjectType, GraphQLSchema, GraphQLUnionType, OperationDefinitionNode } from "graphql";
|
|
2
|
+
import type { Constraint } from "../constraints.js";
|
|
2
3
|
import type { SelectionSetDigest } from "../graphqlCollectFields.js";
|
|
3
4
|
import type { GrafastPlanJSON } from "../index.js";
|
|
4
5
|
import { ExecutableStep } from "../index.js";
|
|
@@ -69,11 +70,11 @@ export declare class OperationPlan {
|
|
|
69
70
|
private scalarPlanInfo;
|
|
70
71
|
constructor(schema: GraphQLSchema, operation: OperationDefinitionNode, fragments: {
|
|
71
72
|
[fragmentName: string]: FragmentDefinitionNode;
|
|
72
|
-
}, variableValues: {
|
|
73
|
+
}, variableValuesConstraints: Constraint[], variableValues: {
|
|
73
74
|
[key: string]: any;
|
|
74
|
-
}, context: {
|
|
75
|
+
}, contextConstraints: Constraint[], context: {
|
|
75
76
|
[key: string]: any;
|
|
76
|
-
}, rootValue: any, planningTimeout: number | null);
|
|
77
|
+
}, rootValueConstraints: Constraint[], rootValue: any, planningTimeout: number | null);
|
|
77
78
|
private lap;
|
|
78
79
|
private checkTimeout;
|
|
79
80
|
private planOperation;
|
|
@@ -198,7 +199,7 @@ export declare class OperationPlan {
|
|
|
198
199
|
*
|
|
199
200
|
* @experimental
|
|
200
201
|
*/
|
|
201
|
-
cacheStep<T extends ExecutableStep>(ownerStep: ExecutableStep, actionKey: string, cacheKey: symbol | string | number, cb: () => T): T;
|
|
202
|
+
cacheStep<T extends ExecutableStep>(ownerStep: ExecutableStep, actionKey: string, cacheKey: symbol | string | number | boolean | null | undefined, cb: () => T): T;
|
|
202
203
|
/**
|
|
203
204
|
* Clears the cache, typically due to side effects having taken place. Called
|
|
204
205
|
* from setting hasSideEffects on an ExecutableStep, among other places.
|
|
@@ -62,7 +62,7 @@ const NO_ARGS = {
|
|
|
62
62
|
},
|
|
63
63
|
};
|
|
64
64
|
class OperationPlan {
|
|
65
|
-
constructor(schema, operation, fragments, variableValues, context, rootValue, planningTimeout) {
|
|
65
|
+
constructor(schema, operation, fragments, variableValuesConstraints, variableValues, contextConstraints, context, rootValueConstraints, rootValue, planningTimeout) {
|
|
66
66
|
this.schema = schema;
|
|
67
67
|
this.operation = operation;
|
|
68
68
|
this.fragments = fragments;
|
|
@@ -96,12 +96,6 @@ class OperationPlan {
|
|
|
96
96
|
this.stepTracker = new StepTracker_js_1.StepTracker(this);
|
|
97
97
|
this.maxDeduplicatedStepId = -1;
|
|
98
98
|
this.maxValidatedStepId = -1;
|
|
99
|
-
/** Constraints based on evaluating variables. @internal */
|
|
100
|
-
this.variableValuesConstraints = [];
|
|
101
|
-
/** Constraints based on evaluating context. @internal */
|
|
102
|
-
this.contextConstraints = [];
|
|
103
|
-
/** Constraints based on evaluating rootValue. @internal */
|
|
104
|
-
this.rootValueConstraints = [];
|
|
105
99
|
/**
|
|
106
100
|
* @internal
|
|
107
101
|
*/
|
|
@@ -138,6 +132,9 @@ class OperationPlan {
|
|
|
138
132
|
};
|
|
139
133
|
this.polymorphicLayerPlanByPathByLayerPlan = new Map();
|
|
140
134
|
this._cacheStepStoreByLayerPlanAndActionKey = Object.create(null);
|
|
135
|
+
this.variableValuesConstraints = variableValuesConstraints;
|
|
136
|
+
this.contextConstraints = contextConstraints;
|
|
137
|
+
this.rootValueConstraints = rootValueConstraints;
|
|
141
138
|
this.scalarPlanInfo = { schema: this.schema };
|
|
142
139
|
const queryType = schema.getQueryType();
|
|
143
140
|
assert.ok(queryType, "Schema must have a query type");
|
|
@@ -1412,6 +1409,16 @@ class OperationPlan {
|
|
|
1412
1409
|
*/
|
|
1413
1410
|
getPeers(step) {
|
|
1414
1411
|
if (step.hasSideEffects) {
|
|
1412
|
+
// Plans with side effects have no peers.
|
|
1413
|
+
return EMPTY_ARRAY;
|
|
1414
|
+
}
|
|
1415
|
+
if (step._stepOptions.stream) {
|
|
1416
|
+
// Streams have no peers - we cannot reference the stream more
|
|
1417
|
+
// than once (and we aim to not cache the stream because we want its
|
|
1418
|
+
// entries to be garbage collected).
|
|
1419
|
+
//
|
|
1420
|
+
// HOWEVER! There may be lifecycle parts that need to be called... So
|
|
1421
|
+
// call the function with an empty array; ignore the result.
|
|
1415
1422
|
return EMPTY_ARRAY;
|
|
1416
1423
|
}
|
|
1417
1424
|
const { dependencies: deps, dependencyForbiddenFlags: flags, dependencyOnReject: onReject, layerPlan: layerPlan, constructor: stepConstructor, peerKey, } = (0, utils_js_1.sudo)(step);
|
|
@@ -1868,24 +1875,12 @@ class OperationPlan {
|
|
|
1868
1875
|
return step;
|
|
1869
1876
|
}
|
|
1870
1877
|
_deduplicateInnerLogic(step) {
|
|
1871
|
-
if (step.hasSideEffects) {
|
|
1872
|
-
// Never deduplicate plans with side effects.
|
|
1873
|
-
return null;
|
|
1874
|
-
}
|
|
1875
1878
|
if (step instanceof index_js_1.__ItemStep) {
|
|
1876
1879
|
// __ItemStep cannot be deduplicated
|
|
1877
1880
|
return null;
|
|
1878
1881
|
}
|
|
1879
|
-
// OPTIMIZE: Past Benjie thought we might want to revisit this under the
|
|
1880
|
-
// new Grafast system. No idea what he had in mind there though...
|
|
1881
|
-
if (step._stepOptions.stream) {
|
|
1882
|
-
// Never deduplicate streaming plans, we cannot reference the stream more
|
|
1883
|
-
// than once (and we aim to not cache the stream because we want its
|
|
1884
|
-
// entries to be garbage collected).
|
|
1885
|
-
return null;
|
|
1886
|
-
}
|
|
1887
1882
|
const peers = this.getPeers(step);
|
|
1888
|
-
// Even if there
|
|
1883
|
+
// Even if there are no peers, we must still deduplicate because
|
|
1889
1884
|
// `deduplicate` is called to indicate that the field is done being
|
|
1890
1885
|
// planned, which the step class may want to acknowledge by locking certain
|
|
1891
1886
|
// facets of its functionality (such as adding filters). We'll simplify its
|
|
@@ -2633,19 +2628,19 @@ class OperationPlan {
|
|
|
2633
2628
|
*/
|
|
2634
2629
|
cacheStep(ownerStep, actionKey, cacheKey, cb) {
|
|
2635
2630
|
const layerPlan = (0, withGlobalLayerPlan_js_1.currentLayerPlan)();
|
|
2636
|
-
const cache = (this._cacheStepStoreByLayerPlanAndActionKey[`${actionKey}|${layerPlan.id}|${ownerStep.id}`] ??=
|
|
2631
|
+
const cache = (this._cacheStepStoreByLayerPlanAndActionKey[`${actionKey}|${layerPlan.id}|${ownerStep.id}`] ??= new Map());
|
|
2637
2632
|
const cacheIt = () => {
|
|
2638
2633
|
const stepToCache = cb();
|
|
2639
2634
|
if (!(stepToCache instanceof index_js_1.ExecutableStep)) {
|
|
2640
2635
|
throw new Error(`The callback passed to cacheStep must always return an ExecutableStep; but this call from ${ownerStep} returned instead ${(0, inspect_js_1.inspect)(stepToCache)}`);
|
|
2641
2636
|
}
|
|
2642
|
-
cache
|
|
2637
|
+
cache.set(cacheKey, stepToCache.id);
|
|
2643
2638
|
return stepToCache;
|
|
2644
2639
|
};
|
|
2645
|
-
if (!(cacheKey
|
|
2640
|
+
if (!cache.has(cacheKey)) {
|
|
2646
2641
|
return cacheIt();
|
|
2647
2642
|
}
|
|
2648
|
-
const cachedStepId = cache
|
|
2643
|
+
const cachedStepId = cache.get(cacheKey);
|
|
2649
2644
|
const cachedStep = this.stepTracker.stepById[cachedStepId];
|
|
2650
2645
|
return cachedStep ?? cacheIt();
|
|
2651
2646
|
}
|
|
@@ -50,7 +50,7 @@ const assertFragmentsMatch = !dev_js_1.isDev ? dev_js_1.noop : reallyAssertFragm
|
|
|
50
50
|
* @remarks Due to the optimisation in `establishOperationPlan`, the schema, document
|
|
51
51
|
* and operationName checks have already been performed.
|
|
52
52
|
*/
|
|
53
|
-
function
|
|
53
|
+
function isOperationPlanResultCompatible(operationPlan, variableValues, context, rootValue) {
|
|
54
54
|
const { variableValuesConstraints, contextConstraints, rootValueConstraints, } = operationPlan;
|
|
55
55
|
if (!(0, constraints_js_1.matchesConstraints)(variableValuesConstraints, variableValues)) {
|
|
56
56
|
return false;
|
|
@@ -84,49 +84,54 @@ function establishOperationPlan(schema, operation, fragments, variableValues, co
|
|
|
84
84
|
let linkedItem = cache.possibleOperationPlans;
|
|
85
85
|
while (linkedItem) {
|
|
86
86
|
const value = linkedItem.value;
|
|
87
|
-
if (value
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
87
|
+
if (isOperationPlanResultCompatible(value, variableValues, context, rootValue)) {
|
|
88
|
+
const { error, operationPlan } = value;
|
|
89
|
+
if (error != null) {
|
|
90
|
+
if (error instanceof index_js_1.SafeError) {
|
|
91
|
+
if (error.extensions?.[interfaces_js_1.$$timeout] != null) {
|
|
92
|
+
if (error.extensions[interfaces_js_1.$$ts] < timeSource_js_1.timeSource.now() - TIMEOUT_TIMEOUT) {
|
|
93
|
+
// Remove this out of date timeout
|
|
94
|
+
linkedItem = linkedItem.next;
|
|
95
|
+
if (previousItem !== null) {
|
|
96
|
+
previousItem.next = linkedItem;
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
cache.possibleOperationPlans = linkedItem;
|
|
100
|
+
}
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
if (planningTimeout !== null &&
|
|
104
|
+
error.extensions[interfaces_js_1.$$timeout] >= planningTimeout) {
|
|
105
|
+
// It was a timeout error - do not retry
|
|
106
|
+
throw error;
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
// That's Not My Timeout, let's try again.
|
|
110
|
+
}
|
|
94
111
|
}
|
|
95
112
|
else {
|
|
96
|
-
|
|
113
|
+
// Not a timeout error - this will always fail in the same way?
|
|
114
|
+
throw error;
|
|
97
115
|
}
|
|
98
|
-
continue;
|
|
99
|
-
}
|
|
100
|
-
if (planningTimeout !== null &&
|
|
101
|
-
value.extensions[interfaces_js_1.$$timeout] >= planningTimeout) {
|
|
102
|
-
// It was a timeout error - do not retry
|
|
103
|
-
throw value;
|
|
104
116
|
}
|
|
105
117
|
else {
|
|
106
|
-
//
|
|
118
|
+
// Not a timeout error - this will always fail in the same way?
|
|
119
|
+
throw error;
|
|
107
120
|
}
|
|
108
121
|
}
|
|
109
122
|
else {
|
|
110
|
-
//
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
// Remove linkedItem from existing chain
|
|
122
|
-
previousItem.next = linkedItem.next;
|
|
123
|
-
// Add rest of chain after linkedItem
|
|
124
|
-
linkedItem.next = cache.possibleOperationPlans;
|
|
125
|
-
// linkedItem is now head of chain
|
|
126
|
-
cache.possibleOperationPlans = linkedItem;
|
|
123
|
+
// Hoist to top of linked list
|
|
124
|
+
if (previousItem !== null) {
|
|
125
|
+
// Remove linkedItem from existing chain
|
|
126
|
+
previousItem.next = linkedItem.next;
|
|
127
|
+
// Add rest of chain after linkedItem
|
|
128
|
+
linkedItem.next = cache.possibleOperationPlans;
|
|
129
|
+
// linkedItem is now head of chain
|
|
130
|
+
cache.possibleOperationPlans = linkedItem;
|
|
131
|
+
}
|
|
132
|
+
// We found a suitable OperationPlan - use that!
|
|
133
|
+
return operationPlan;
|
|
127
134
|
}
|
|
128
|
-
// We found a suitable OperationPlan - use that!
|
|
129
|
-
return value;
|
|
130
135
|
}
|
|
131
136
|
count++;
|
|
132
137
|
lastButOneItem = previousItem;
|
|
@@ -137,8 +142,11 @@ function establishOperationPlan(schema, operation, fragments, variableValues, co
|
|
|
137
142
|
// No suitable OperationPlan found, time to make one.
|
|
138
143
|
let operationPlan;
|
|
139
144
|
let error;
|
|
145
|
+
const variableValuesConstraints = [];
|
|
146
|
+
const contextConstraints = [];
|
|
147
|
+
const rootValueConstraints = [];
|
|
140
148
|
try {
|
|
141
|
-
operationPlan = new index_js_1.OperationPlan(schema, operation, fragments, variableValues, context, rootValue, planningTimeout);
|
|
149
|
+
operationPlan = new index_js_1.OperationPlan(schema, operation, fragments, variableValuesConstraints, variableValues, contextConstraints, context, rootValueConstraints, rootValue, planningTimeout);
|
|
142
150
|
}
|
|
143
151
|
catch (e) {
|
|
144
152
|
error = e;
|
|
@@ -153,11 +161,19 @@ function establishOperationPlan(schema, operation, fragments, variableValues, co
|
|
|
153
161
|
});
|
|
154
162
|
schema.extensions.grafast[interfaces_js_1.$$cacheByOperation] = cacheByOperation;
|
|
155
163
|
}
|
|
156
|
-
const
|
|
164
|
+
const establishOperationPlanResult = {
|
|
165
|
+
variableValuesConstraints,
|
|
166
|
+
contextConstraints,
|
|
167
|
+
rootValueConstraints,
|
|
168
|
+
...(operationPlan ? { operationPlan } : { error: error }),
|
|
169
|
+
};
|
|
157
170
|
if (!cache) {
|
|
158
171
|
cache = {
|
|
159
172
|
fragments,
|
|
160
|
-
possibleOperationPlans: {
|
|
173
|
+
possibleOperationPlans: {
|
|
174
|
+
value: establishOperationPlanResult,
|
|
175
|
+
next: null,
|
|
176
|
+
},
|
|
161
177
|
};
|
|
162
178
|
cacheByOperation.set(operation, cache);
|
|
163
179
|
}
|
|
@@ -171,7 +187,7 @@ function establishOperationPlan(schema, operation, fragments, variableValues, co
|
|
|
171
187
|
}
|
|
172
188
|
// Add new operationPlan to top of the linked list.
|
|
173
189
|
cache.possibleOperationPlans = {
|
|
174
|
-
value:
|
|
190
|
+
value: establishOperationPlanResult,
|
|
175
191
|
next: cache.possibleOperationPlans,
|
|
176
192
|
};
|
|
177
193
|
}
|
package/dist/inspect.js
CHANGED
package/dist/interfaces.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import type EventEmitter from "eventemitter3";
|
|
|
2
2
|
import type { Middleware } from "graphile-config";
|
|
3
3
|
import type { ASTNode, ExecutionArgs, FragmentDefinitionNode, GraphQLArgs, GraphQLArgument, GraphQLArgumentConfig, GraphQLField, GraphQLFieldConfig, GraphQLInputField, GraphQLInputFieldConfig, GraphQLInputObjectType, GraphQLInputType, GraphQLList, GraphQLNonNull, GraphQLOutputType, GraphQLScalarType, GraphQLSchema, GraphQLType, OperationDefinitionNode, Source, ValueNode, VariableNode } from "graphql";
|
|
4
4
|
import type { ObjMap } from "graphql/jsutils/ObjMap.js";
|
|
5
|
+
import type { Constraint } from "./constraints.js";
|
|
5
6
|
import type { OperationPlan } from "./engine/OperationPlan.js";
|
|
6
7
|
import type { FlaggedValue, SafeError } from "./error.js";
|
|
7
8
|
import type { ExecutableStep, ListCapableStep, ModifierStep, StreamableStep } from "./step.js";
|
|
@@ -38,13 +39,26 @@ export declare const $$cacheByOperation: unique symbol;
|
|
|
38
39
|
export type Fragments = {
|
|
39
40
|
[key: string]: FragmentDefinitionNode;
|
|
40
41
|
};
|
|
41
|
-
export
|
|
42
|
-
[
|
|
43
|
-
[
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
42
|
+
export interface IEstablishOperationPlanResult {
|
|
43
|
+
variableValuesConstraints: Constraint[];
|
|
44
|
+
contextConstraints: Constraint[];
|
|
45
|
+
rootValueConstraints: Constraint[];
|
|
46
|
+
}
|
|
47
|
+
export interface EstablishOperationPlanResultSuccess extends IEstablishOperationPlanResult {
|
|
48
|
+
error?: never;
|
|
49
|
+
operationPlan: OperationPlan;
|
|
50
|
+
}
|
|
51
|
+
export interface EstablishOperationPlanResultError extends IEstablishOperationPlanResult {
|
|
52
|
+
error: Error | SafeError<{
|
|
53
|
+
[$$timeout]: number;
|
|
54
|
+
[$$ts]: number;
|
|
55
|
+
} | {
|
|
56
|
+
[$$timeout]?: undefined;
|
|
57
|
+
[$$ts]?: undefined;
|
|
58
|
+
} | undefined>;
|
|
59
|
+
operationPlan?: never;
|
|
60
|
+
}
|
|
61
|
+
export type EstablishOperationPlanResult = EstablishOperationPlanResultSuccess | EstablishOperationPlanResultError;
|
|
48
62
|
/**
|
|
49
63
|
* This represents the list of possible operationPlans for a specific document.
|
|
50
64
|
*
|
|
@@ -59,7 +73,7 @@ export interface CacheByOperationEntry {
|
|
|
59
73
|
* list, and if the list grows beyond a maximum size we can drop the last
|
|
60
74
|
* element.
|
|
61
75
|
*/
|
|
62
|
-
possibleOperationPlans: LinkedList<
|
|
76
|
+
possibleOperationPlans: LinkedList<EstablishOperationPlanResult> | null;
|
|
63
77
|
fragments: Fragments;
|
|
64
78
|
}
|
|
65
79
|
export interface LinkedList<T> {
|
package/dist/version.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const version = "0.1.1-beta.
|
|
1
|
+
export declare const version = "0.1.1-beta.20";
|
|
2
2
|
//# sourceMappingURL=version.d.ts.map
|
package/dist/version.js
CHANGED