Skip to content

Commit

Permalink
Remove lookahead hack (#109)
Browse files Browse the repository at this point in the history
  • Loading branch information
DmitryTsepelev committed Mar 24, 2024
1 parent 8849784 commit 82a8164
Show file tree
Hide file tree
Showing 10 changed files with 94 additions and 66 deletions.
3 changes: 2 additions & 1 deletion .github/workflows/rspec.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,15 @@ jobs:
strategy:
fail-fast: false
matrix:
ruby: ['3.0', 3.1, 3.2]
ruby: ['3.0', 3.1, 3.3]
gemfile: [
"gemfiles/graphql_1_12_0.gemfile",
"gemfiles/graphql_1_13_7.gemfile",
"gemfiles/graphql_2_0_0.gemfile",
"gemfiles/graphql_2_0_14.gemfile",
"gemfiles/graphql_2_1_0.gemfile",
"gemfiles/graphql_2_1_4.gemfile",
"gemfiles/graphql_2_3_0.gemfile",
"gemfiles/graphql_master.gemfile"
]

Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ Gemfile.lock
.DS_Store
.rbnext/
*.sqlite3
*.sqlite3-*
spec/internal/log/*.log
.idea/
.ruby-version
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

## master

- [PR#109](https://github.com/DmitryTsepelev/graphql-ruby-fragment_cache/pull/109) Remove `Lookahead` patch in modern versions of graphql-ruby ([@DmitryTsepelev][])

## 1.20.0 (2024-03-02)

- [PR#108](https://github.com/DmitryTsepelev/graphql-ruby-fragment_cache/pull/108) Use trace_with instead of deprecated instrument method ([@camero2734][])
Expand Down
5 changes: 5 additions & 0 deletions gemfiles/graphql_2_3_0.gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
source "https://rubygems.org"

gem "graphql", "~> 2.3.0"

gemspec path: "../"
22 changes: 4 additions & 18 deletions lib/graphql/fragment_cache.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

require "graphql"

require "graphql/fragment_cache/graphql_ruby_version"

require "graphql/fragment_cache/ext/context_fragments"
require "graphql/fragment_cache/ext/graphql_cache_key"
require "graphql/fragment_cache/object"
Expand Down Expand Up @@ -33,7 +35,7 @@ def use(schema_defn, options = {})

schema_defn.tracer(Schema::Tracer)

if graphql_ruby_after_2_2_5?
if GraphRubyVersion.after_2_2_5?
schema_defn.trace_with(GraphQL::Tracing::LegacyHooksTrace)
schema_defn.instance_exec { own_instrumenters[:query] << Schema::Instrumentation }
else
Expand Down Expand Up @@ -64,30 +66,14 @@ def cache_store=(store)

alias_method :skip_cache_when_query_has_errors?, :skip_cache_when_query_has_errors

def graphql_ruby_before_2_0?
check_graphql_version "< 2.0.0"
end

def graphql_ruby_after_2_0_13?
check_graphql_version "> 2.0.13"
end

def graphql_ruby_before_2_1_4?
check_graphql_version "< 2.1.4"
end

def graphql_ruby_after_2_2_5?
check_graphql_version "> 2.2.5"
end

private

def check_graphql_version(predicate)
Gem::Dependency.new("graphql", predicate).match?("graphql", GraphQL::VERSION)
end

def verify_interpreter_and_analysis!(schema_defn)
if graphql_ruby_before_2_0?
if GraphRubyVersion.before_2_0?
unless schema_defn.interpreter?
raise StandardError,
"GraphQL::Execution::Interpreter should be enabled for fragment caching"
Expand Down
90 changes: 46 additions & 44 deletions lib/graphql/fragment_cache/cache_key_builder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -53,64 +53,66 @@ def selection_with_alias(name, **kwargs)
alias_selection(name, **kwargs)
end

def alias_selection(name, selected_type: @selected_type, arguments: nil)
return alias_selections[name] if alias_selections.key?(name)
if GraphRubyVersion.before_2_1_4?
def alias_selection(name, selected_type: @selected_type, arguments: nil)
return alias_selections[name] if alias_selections.key?(name)

alias_node = lookup_alias_node(ast_nodes, name)
return ::GraphQL::Execution::Lookahead::NULL_LOOKAHEAD unless alias_node
alias_node = lookup_alias_node(ast_nodes, name)
return ::GraphQL::Execution::Lookahead::NULL_LOOKAHEAD unless alias_node

next_field_name = alias_node.name
next_field_name = alias_node.name

# From https://github.com/rmosolgo/graphql-ruby/blob/1a9a20f3da629e63ea8e5ee8400be82218f9edc3/lib/graphql/execution/lookahead.rb#L91
next_field_defn =
if GraphQL::FragmentCache.graphql_ruby_before_2_0?
get_class_based_field(selected_type, next_field_name)
else
@query.get_field(selected_type, next_field_name)
end
# From https://github.com/rmosolgo/graphql-ruby/blob/1a9a20f3da629e63ea8e5ee8400be82218f9edc3/lib/graphql/execution/lookahead.rb#L91
next_field_defn =
if GraphRubyVersion.before_2_0?
get_class_based_field(selected_type, next_field_name)
else
@query.get_field(selected_type, next_field_name)
end

alias_selections[name] =
if next_field_defn
next_nodes = []
arguments = @query.arguments_for(alias_node, next_field_defn)
arguments = arguments.is_a?(::GraphQL::Execution::Interpreter::Arguments) ? arguments.keyword_arguments : arguments
@ast_nodes.each do |ast_node|
ast_node.selections.each do |selection|
if GraphQL::FragmentCache.graphql_ruby_after_2_0_13? && GraphQL::FragmentCache.graphql_ruby_before_2_1_4?
find_selected_nodes(selection, next_field_defn, arguments: arguments, matches: next_nodes)
else
find_selected_nodes(selection, next_field_name, next_field_defn, arguments: arguments, matches: next_nodes)
alias_selections[name] =
if next_field_defn
next_nodes = []
arguments = @query.arguments_for(alias_node, next_field_defn)
arguments = arguments.is_a?(::GraphQL::Execution::Interpreter::Arguments) ? arguments.keyword_arguments : arguments
@ast_nodes.each do |ast_node|
ast_node.selections.each do |selection|
if GraphRubyVersion.after_2_0_13? && GraphRubyVersion.before_2_1_4?
find_selected_nodes(selection, next_field_defn, arguments: arguments, matches: next_nodes)
else
find_selected_nodes(selection, next_field_name, next_field_defn, arguments: arguments, matches: next_nodes)
end
end
end
end

if next_nodes.any?
::GraphQL::Execution::Lookahead.new(query: @query, ast_nodes: next_nodes, field: next_field_defn, owner_type: selected_type)
if next_nodes.any?
::GraphQL::Execution::Lookahead.new(query: @query, ast_nodes: next_nodes, field: next_field_defn, owner_type: selected_type)
else
::GraphQL::Execution::Lookahead::NULL_LOOKAHEAD
end
else
::GraphQL::Execution::Lookahead::NULL_LOOKAHEAD
end
else
::GraphQL::Execution::Lookahead::NULL_LOOKAHEAD
end
end
end

def alias_selections
return @alias_selections if defined?(@alias_selections)
@alias_selections ||= {}
end
def alias_selections
return @alias_selections if defined?(@alias_selections)
@alias_selections ||= {}
end

def lookup_alias_node(nodes, name)
return if nodes.empty?
def lookup_alias_node(nodes, name)
return if nodes.empty?

nodes.find do |node|
if node.is_a?(GraphQL::Language::Nodes::FragmentSpread)
node = @query.fragments[node.name]
raise("Invariant: Can't look ahead to nonexistent fragment #{node.name} (found: #{@query.fragments.keys})") unless node
end
nodes.find do |node|
if node.is_a?(GraphQL::Language::Nodes::FragmentSpread)
node = @query.fragments[node.name]
raise("Invariant: Can't look ahead to nonexistent fragment #{node.name} (found: #{@query.fragments.keys})") unless node
end

return node if node.alias?(name)
child = lookup_alias_node(node.children, name)
return child if child
return node if node.alias?(name)
child = lookup_alias_node(node.children, name)
return child if child
end
end
end
end
Expand Down
31 changes: 31 additions & 0 deletions lib/graphql/fragment_cache/graphql_ruby_version.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# frozen_string_literal: true

using RubyNext

module GraphQL
module FragmentCache
module GraphRubyVersion
module_function

def before_2_0?
check_graphql_version "< 2.0.0"
end

def after_2_0_13?
check_graphql_version "> 2.0.13"
end

def before_2_1_4?
check_graphql_version "< 2.1.4"
end

def after_2_2_5?
check_graphql_version "> 2.2.5"
end

def check_graphql_version(predicate)
Gem::Dependency.new("graphql", predicate).match?("graphql", GraphQL::VERSION)
end
end
end
end
2 changes: 1 addition & 1 deletion spec/graphql/fragment_cache_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

describe GraphQL::FragmentCache do
describe ".use" do
if GraphQL::FragmentCache.graphql_ruby_before_2_0?
if GraphQL::FragmentCache::GraphRubyVersion.before_2_0?
it "raises if interpreter is not used" do
expect {
Class.new(GraphQL::Schema) {
Expand Down
2 changes: 1 addition & 1 deletion spec/support/schema_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
module SchemaHelper
def build_schema(&block)
Class.new(GraphQL::Schema) do
if GraphQL::FragmentCache.graphql_ruby_before_2_0?
if GraphQL::FragmentCache::GraphRubyVersion.before_2_0?
use GraphQL::Execution::Interpreter
use GraphQL::Analysis::AST

Expand Down
2 changes: 1 addition & 1 deletion spec/support/test_schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ def cached_post_by_complex_input(complex_post_input:)
end

class TestSchema < GraphQL::Schema
if GraphQL::FragmentCache.graphql_ruby_before_2_0?
if GraphQL::FragmentCache::GraphRubyVersion.before_2_0?
use GraphQL::Execution::Interpreter
use GraphQL::Analysis::AST

Expand Down

0 comments on commit 82a8164

Please sign in to comment.