Skip to content

Commit 5536a82

Browse files
committed
initial draft of plan options
1 parent f2b3740 commit 5536a82

File tree

1 file changed

+98
-0
lines changed

1 file changed

+98
-0
lines changed

spec/Section 5 -- Execution.md

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,101 @@ request.
1010
The supergraph is a GraphQL IDL document that contains metadata for the query
1111
planner that describes the relationship between type system members and the type
1212
system members on subgraphs.
13+
14+
## PlanOptions Algorithm
15+
16+
The PlanOptions algorithm computes which source schemas (options) can resolve a specific path in the
17+
composite schema. The algorithm examines each step of the path to determine which source schemas can
18+
fulfill the requested fields.
19+
20+
### Formal Specification
21+
22+
me
23+
24+
Query.me.profile.age
25+
[
26+
(Query, me),
27+
(User, profile),
28+
(Profile, age)
29+
]
30+
31+
Mutation.createUser.query.me
32+
[
33+
(Mutation, createUser),
34+
(CreateUserPayload, query),
35+
(Query, me)
36+
]
37+
// Technically the first item doesnt have to check all source schemas twice (inintializ eoptions as [])
38+
//
39+
40+
41+
42+
PlanOptions(path):
43+
44+
45+
- Let {pathElements} be the list of tuples ({type}, {field}) in the provided {path}.
46+
47+
- Let ({initialType}, {initialField}) be the first element in {pathElements}.
48+
49+
- Let {sourceSchemas} be an empty set.
50+
- For each {sourceSchema} in all source schemas:
51+
- If {sourceSchema} does not define {initialType}.{initialField}
52+
- Continue to the next {sourceSchema}.
53+
- Add {sourceSchema} to {sourceSchemas}.
54+
55+
- For each {pathElement} in {pathElements} starting from the second element:
56+
- Initialize a new empty set {nextSchemas}.
57+
- Set {currentType} and {currentField} to the respective elements of the current {pathElement}.
58+
- For each {currentSchema} in {sourceSchemas}:
59+
- For each {candidateSchema} in all source schemas:
60+
- If {candidateSchema} does not define {currentType}.{currentField}
61+
- Continue to the next {candidateSchema}.
62+
63+
- If {candidateSchema} not equals {currentSchema}:
64+
- Continue to the next {candidateSchema}.
65+
- If {IsReachable(option, candidateSchema, currentType)} returns false:
66+
- Continue to the next {candidateSchema}.
67+
68+
- If {currentField} on {currentType} in {candidateSchema} defines a requirement:
69+
- If {ResolveRequirement(candidateSchema, currentType, currentField)} returns a valid requirement:
70+
- If the requirement is not satisfied by {currentSchema}:
71+
- Continue to the next {candidateSchema}.
72+
- Add {candidateSchema} to {nextSchemas}.
73+
74+
- If {nextSchemas} is empty after:
75+
- Return an empty set.
76+
77+
- Set {sourceSchemas} equal to {nextSchemas} to proceed to the next element in the path.
78+
79+
- return {sourceSchemas}.
80+
81+
IsReachable(sourceSchema, targetSchema, type):
82+
- If {targetSchema} does not define {type}
83+
- return false
84+
- If {sourceSchema} equals {targetSchema}
85+
- return true
86+
- Let {lookups} be the set of all lookup fields in {targetSchema} that return {type}
87+
- For each {lookup} in {lookups}:
88+
- Let {keyFields} be the set of fields that form the key for {lookup} in {targetSchema}
89+
- If {keyFields} is empty
90+
- return false // ??
91+
- For each {keyField} in {keyFields}:
92+
- PlanOptions({keyField}) ??
93+
- return false
94+
95+
ResolveRequirement(schema, type, field):
96+
- Let {requirements} be the parsed selection map from requirements on {field}
97+
- Let {otherSchemas} be the set of all source schemas excluding {schema}
98+
- For each {requiredField} in {requirements}:
99+
- Let {fieldPath} be the path to {requiredField} starting from {type}
100+
- Let {canResolve} be false
101+
- For each {otherSchema} in {otherSchemas}:
102+
- If {otherSchema} defines {type} and {fieldPath}
103+
- If {IsReachable(schema, otherSchema, type)} returns true
104+
- Set {canResolve} to true
105+
- Break
106+
- If {canResolve} is false
107+
- return false
108+
- return true
109+
110+

0 commit comments

Comments
 (0)