Skip to content
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

Use new resolver metadata for aggregation resolvers. #169

Draft
wants to merge 1 commit into
base: myron/improve-perf/migrate-nested-relationships
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
177 changes: 177 additions & 0 deletions config/schema/artifacts/runtime_metadata.yaml

Large diffs are not rendered by default.

177 changes: 177 additions & 0 deletions config/schema/artifacts_with_apollo/runtime_metadata.yaml

Large diffs are not rendered by default.

6 changes: 5 additions & 1 deletion elasticgraph-graphql/lib/elastic_graph/graphql.rb
Original file line number Diff line number Diff line change
Expand Up @@ -185,14 +185,18 @@ def graphql_resolvers
def named_graphql_resolvers
@named_graphql_resolvers ||= begin
require "elastic_graph/graphql/resolvers/nested_relationships"
require "elastic_graph/graphql/resolvers/object"

nested_relationships = Resolvers::NestedRelationships.new(
resolver_query_adapter: resolver_query_adapter,
schema_element_names: runtime_metadata.schema_element_names,
logger: logger
)

{nested_relationships: nested_relationships}
{
nested_relationships: nested_relationships,
object: Resolvers::Object.new
}
end
end

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,6 @@ class GraphQL
module Aggregation
module Resolvers
class AggregatedValues < ::Data.define(:aggregation_name, :bucket, :field_path)
def can_resolve?(field:, object:)
true
end

def call(parent_type, graphql_field, object, args, context)
field = context.fetch(:elastic_graph_schema).field_named(parent_type.graphql_name, graphql_field.name)
return with(field_path: field_path + [PathSegment.for(field: field, lookahead: args.fetch(:lookahead))]) if field.type.object?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,6 @@ class GraphQL
module Aggregation
module Resolvers
class GroupedBy < ::Data.define(:bucket, :field_path)
def can_resolve?(field:, object:)
true
end

def call(parent_type, graphql_field, object, args, context)
field = context.fetch(:elastic_graph_schema).field_named(parent_type.graphql_name, graphql_field.name)
new_field_path = field_path + [PathSegment.for(field: field, lookahead: args.fetch(:lookahead))]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,6 @@ class GraphQL
module Aggregation
module Resolvers
class SubAggregations < ::Data.define(:schema_element_names, :sub_aggregations, :parent_queries, :sub_aggs_by_agg_key, :field_path)
def can_resolve?(field:, object:)
true
end

def call(parent_type, graphql_field, object, args, context)
field = context.fetch(:elastic_graph_schema).field_named(parent_type.graphql_name, graphql_field.name)
path_segment = PathSegment.for(field: field, lookahead: args.fetch(:lookahead))
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Copyright 2024 Block, Inc.
#
# Use of this source code is governed by an MIT-style
# license that can be found in the LICENSE file or at
# https://opensource.org/licenses/MIT.
#
# frozen_string_literal: true

module ElasticGraph
class GraphQL
module Resolvers
# Resolver which just delegates to `object` for resolving.
class Object
def call(parent_type, graphql_field, object, args, context)
object.call(parent_type, graphql_field, object, args, context)
end
end
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ def initialize(schema, parent_type, graphql_field, runtime_metadata)
@graphql_field = graphql_field
@relation = runtime_metadata&.relation
@computation_detail = runtime_metadata&.computation_detail
@resolver = runtime_metadata&.resolver
@resolver = runtime_metadata&.resolver || parent_type.default_graphql_resolver
@name_in_index = runtime_metadata&.name_in_index&.to_sym || name

# Adds the :extras required by ElasticGraph. For now, this blindly adds `:lookahead`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class GraphQL
class Schema
# Represents a GraphQL type.
class Type
attr_reader :graphql_type, :fields_by_name, :index_definitions, :elasticgraph_category, :graphql_only_return_type
attr_reader :graphql_type, :fields_by_name, :index_definitions, :elasticgraph_category, :graphql_only_return_type, :default_graphql_resolver

def initialize(
schema,
Expand All @@ -36,6 +36,7 @@ def initialize(
@object_runtime_metadata = object_runtime_metadata
@elasticgraph_category = object_runtime_metadata&.elasticgraph_category
@graphql_only_return_type = object_runtime_metadata&.graphql_only_return_type
@default_graphql_resolver = object_runtime_metadata&.default_graphql_resolver
@enum_runtime_metadata = enum_runtime_metadata
@enum_value_names_by_original_name = (enum_runtime_metadata&.values_by_name || {}).to_h do |name, value|
[value.alternate_original_name || name, name]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ module ElasticGraph
type fieldArgs = ::Hash[::Symbol, untyped]

interface _Resolver
def can_resolve?: (field: Schema::Field, object: untyped) -> bool
def call: (
::GraphQL::Schema::_Type,
::GraphQL::Schema::Field,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
module ElasticGraph
class GraphQL
module Resolvers
class Object
include _Resolver
end
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,10 @@ def new_aggregated_values_type_for_index_leaf_type(index_leaf_type)
new_object_type @state.type_ref(index_leaf_type).as_aggregated_values.name do |type|
type.graphql_only true
type.documentation "A return type used from aggregations to provided aggregated values over `#{index_leaf_type}` fields."
type.runtime_metadata_overrides = {elasticgraph_category: :scalar_aggregated_values}
type.runtime_metadata_overrides = {
elasticgraph_category: :scalar_aggregated_values,
default_graphql_resolver: :object
}

type.field @state.schema_elements.approximate_distinct_value_count, "JsonSafeLong", graphql_only: true do |f|
# Note: the 1-6% accuracy figure comes from the Elasticsearch docs:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ def sub_aggregation_types_for_nested_field_references
schema_def_state.sub_aggregation_paths_for(nested_field_ref.parent_type).map do |path|
schema_def_state.factory.new_object_type type_ref.as_sub_aggregation(parent_doc_types: path.parent_doc_types).name do |t|
t.documentation "Return type representing a bucket of `#{name}` objects for a sub-aggregation within each `#{type_ref.as_parent_aggregation(parent_doc_types: path.parent_doc_types).name}`."
t.runtime_metadata_overrides = {default_graphql_resolver: :object}

t.field schema_def_state.schema_elements.count_detail, "AggregationCountDetail", graphql_only: true do |f|
f.documentation "Details of the count of `#{name}` documents in a sub-aggregation bucket."
Expand Down Expand Up @@ -163,6 +164,7 @@ def build_aggregation_sub_aggregations_types
schema_def_state.factory.new_object_type agg_sub_aggs_type_ref.name do |t|
under_field_description = "under `#{path.field_path_string}` " unless path.field_path.empty?
t.documentation "Provides access to the `#{schema_def_state.schema_elements.sub_aggregations}` #{under_field_description}within each `#{type_ref.as_parent_aggregation(parent_doc_types: path.parent_doc_types).name}`."
t.runtime_metadata_overrides = {default_graphql_resolver: :object}

sub_aggregatable_fields.each do |field|
if field.nested?
Expand Down Expand Up @@ -225,7 +227,11 @@ def to_indexed_aggregation_type

# Record metadata that is necessary for elasticgraph-graphql to correctly recognize and handle
# this indexed aggregation type correctly.
t.runtime_metadata_overrides = {source_type: name, elasticgraph_category: :indexed_aggregation}
t.runtime_metadata_overrides = {
source_type: name,
elasticgraph_category: :indexed_aggregation,
default_graphql_resolver: :object
}
end
end

Expand All @@ -236,6 +242,7 @@ def to_grouped_by_type

new_non_empty_object_type type_ref.as_grouped_by.name do |t|
t.documentation "Type used to specify the `#{name}` fields to group by for aggregations."
t.runtime_metadata_overrides = {default_graphql_resolver: :object}

graphql_fields_by_name.values.each do |field|
field.define_grouped_by_field(t)
Expand All @@ -250,6 +257,7 @@ def to_aggregated_values_type

new_non_empty_object_type type_ref.as_aggregated_values.name do |t|
t.documentation "Type used to perform aggregation computations on `#{name}` fields."
t.runtime_metadata_overrides = {default_graphql_resolver: :object}

graphql_fields_by_name.values.each do |field|
field.define_aggregated_values_field(t)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -509,6 +509,7 @@ def register_standard_elastic_graph_types

register_framework_object_type "AggregationCountDetail" do |t|
t.documentation "Provides detail about an aggregation `#{names.count}`."
t.runtime_metadata_overrides = {default_graphql_resolver: :object}

t.field names.approximate_value, "JsonSafeLong!", graphql_only: true do |f|
f.documentation <<~EOS
Expand Down Expand Up @@ -1290,7 +1291,10 @@ def register_date_and_time_grouped_by_types
date = schema_def_state.type_ref("Date")
register_framework_object_type date.as_grouped_by.name do |t|
t.documentation "Allows for grouping `Date` values based on the desired return type."
t.runtime_metadata_overrides = {elasticgraph_category: :date_grouped_by_object}
t.runtime_metadata_overrides = {
elasticgraph_category: :date_grouped_by_object,
default_graphql_resolver: :object
}

t.field names.as_date, "Date", graphql_only: true do |f|
f.documentation "Used when grouping on the full `Date` value."
Expand All @@ -1307,7 +1311,10 @@ def register_date_and_time_grouped_by_types
date_time = schema_def_state.type_ref("DateTime")
register_framework_object_type date_time.as_grouped_by.name do |t|
t.documentation "Allows for grouping `DateTime` values based on the desired return type."
t.runtime_metadata_overrides = {elasticgraph_category: :date_grouped_by_object}
t.runtime_metadata_overrides = {
elasticgraph_category: :date_grouped_by_object,
default_graphql_resolver: :object
}

t.field names.as_date_time, "DateTime", graphql_only: true do |f|
f.documentation "Used when grouping on the full `DateTime` value."
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,9 @@ module SchemaDefinition
LongStringAggregatedValues
LongStringListFilterInput
MatchesQueryAllowedEditsPerTermListFilterInput
NoCustomizationsAggregatedValues
NoCustomizationsFieldsListFilterInput
NoCustomizationsGroupedBy
NoCustomizationsListFilterInput
NonNumericAggregatedValues
PageInfo
Expand Down