-
Notifications
You must be signed in to change notification settings - Fork 1.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[v3] Complexity cost bug fixes #4843
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -44,6 +44,10 @@ def initialize(parent_type, field_definition, query, response_path) | |
def own_complexity(child_complexity) | ||
@field_definition.calculate_complexity(query: @query, nodes: @nodes, child_complexity: child_complexity) | ||
end | ||
|
||
def composite? | ||
!empty? | ||
end | ||
end | ||
|
||
def on_enter_field(node, parent, visitor) | ||
|
@@ -145,35 +149,38 @@ def merged_max_complexity(query, inner_selections) | |
|
||
# Add up the total cost for each unique field name's coalesced selections | ||
unique_field_keys.each_key.reduce(0) do |total, field_key| | ||
composite_scopes = nil | ||
field_cost = 0 | ||
|
||
# Collect composite selection scopes for further aggregation, | ||
# leaf selections report their costs directly. | ||
inner_selections.each do |inner_selection| | ||
child_scope = inner_selection[field_key] | ||
next unless child_scope | ||
|
||
# Empty child scopes are leaf nodes with zero child complexity. | ||
if child_scope.empty? | ||
field_cost = child_scope.own_complexity(0) | ||
field_complexity(child_scope, max_complexity: field_cost, child_complexity: nil) | ||
# Collect all child scopes for this field key; | ||
# all keys come with at least one scope. | ||
child_scopes = inner_selections.filter_map { _1[field_key] } | ||
|
||
# Compute maximum possible cost of child selections; | ||
# composites merge their maximums, while leaf scopes are always zero. | ||
# FieldsWillMerge validation assures all scopes are uniformly composite or leaf. | ||
maximum_children_cost = if child_scopes.any?(&:composite?) | ||
merged_max_complexity_for_scopes(query, child_scopes) | ||
else | ||
0 | ||
end | ||
|
||
# Identify the maximum cost and scope among possibilities | ||
maximum_cost = 0 | ||
maximum_scope = child_scopes.reduce(child_scopes.last) do |max_scope, possible_scope| | ||
scope_cost = possible_scope.own_complexity(maximum_children_cost) | ||
if scope_cost > maximum_cost | ||
maximum_cost = scope_cost | ||
possible_scope | ||
else | ||
composite_scopes ||= [] | ||
composite_scopes << child_scope | ||
max_scope | ||
end | ||
end | ||
|
||
if composite_scopes | ||
child_complexity = merged_max_complexity_for_scopes(query, composite_scopes) | ||
|
||
# This is the last composite scope visited; assume it's representative (for backwards compatibility). | ||
# Note: it would be more correct to score each composite scope and use the maximum possibility. | ||
field_cost = composite_scopes.last.own_complexity(child_complexity) | ||
field_complexity(composite_scopes.last, max_complexity: field_cost, child_complexity: child_complexity) | ||
end | ||
field_complexity( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Lastly, always trigger exactly one hook per field with the resolved maximums among scopes, costs, and children costs. Before leaf scopes would receive |
||
maximum_scope, | ||
max_complexity: maximum_cost, | ||
child_complexity: maximum_children_cost, | ||
) | ||
|
||
total + field_cost | ||
total + maximum_cost | ||
end | ||
end | ||
end | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This switches to always hill-climb for the maximum possibility among scopes, regardless if they are leaf or composite scopes.