Skip to content

Defer directive #168

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

Closed
wants to merge 10 commits into from
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ language: ruby
sudo: false
cache: bundler
env: CODECLIMATE_REPO_TOKEN=f5b27b2e25d3f4e199bb2566fb4fd4507144a004c71d4aa33a32c2df5f940333
script: bundle exec test_both_strategies

rvm:
- 2.1.0 # Lowest version officially supported by that gem
Expand Down
8 changes: 7 additions & 1 deletion Rakefile
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,20 @@ Rake::TestTask.new do |t|
t.warning = false
end

desc "Run the test suite on both built-in execution strategies"
task :test_both_strategies do
system "bundle exec rake test"
system "GRAPHQL_EXEC_STRATEGY=serial bundle exec rake test"
end

require 'rubocop/rake_task'
RuboCop::RakeTask.new(:rubocop) do |t|
t.patterns = Rake::FileList['lib/**/{*}.rb', 'spec/**/*.rb']
.exclude("lib/graphql/language/parser.rb")
.exclude("lib/graphql/language/lexer.rb")
end

task(default: [:test, :rubocop])
task(default: [:test_both_strategies, :rubocop])

desc "Use Racc & Ragel to regenerate parser.rb & lexer.rb from configuration files"
task :build_parser do
Expand Down
1 change: 1 addition & 0 deletions lib/graphql/define.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
require "graphql/define/assign_argument"
require "graphql/define/assign_batch_resolve"
require "graphql/define/assign_connection"
require "graphql/define/assign_enum_value"
require "graphql/define/assign_global_id_field"
Expand Down
10 changes: 10 additions & 0 deletions lib/graphql/define/assign_batch_resolve.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
module GraphQL
module Define
module AssignBatchResolve
def self.call(field_defn, loader, *loader_args, resolve_func)
field_defn.batch_loader = GraphQL::Execution::Batch::BatchLoader.new(loader, loader_args)
field_defn.resolve = resolve_func
end
end
end
end
2 changes: 2 additions & 0 deletions lib/graphql/directive.rb
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ def on_operation?
end
end

require "graphql/directive/defer_directive"
require "graphql/directive/include_directive"
require "graphql/directive/skip_directive"
require "graphql/directive/deprecated_directive"
require "graphql/directive/stream_directive"
5 changes: 5 additions & 0 deletions lib/graphql/directive/defer_directive.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
GraphQL::Directive::DeferDirective = GraphQL::Directive.define do
name "defer"
description "Push this part of the query in a later patch"
locations([GraphQL::Directive::FIELD, GraphQL::Directive::FRAGMENT_SPREAD, GraphQL::Directive::INLINE_FRAGMENT])
end
5 changes: 5 additions & 0 deletions lib/graphql/directive/stream_directive.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
GraphQL::Directive::StreamDirective = GraphQL::Directive.define do
name "stream"
description "Push items from this list in sequential patches"
locations([GraphQL::Directive::FIELD])
end
8 changes: 8 additions & 0 deletions lib/graphql/execution.rb
Original file line number Diff line number Diff line change
@@ -1,2 +1,10 @@
require "graphql/execution/batch"
require "graphql/execution/deferred_execution"
require "graphql/execution/directive_checks"
require "graphql/execution/exec_frame"
require "graphql/execution/exec_scope"
require "graphql/execution/exec_stream"
require "graphql/execution/exec_thread"
require "graphql/execution/merge_branch_result"
require "graphql/execution/merge_collector"
require "graphql/execution/typecast"
63 changes: 63 additions & 0 deletions lib/graphql/execution/batch.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
module GraphQL
module Execution
module Batch
def self.resolve(item_arg, func)
BatchResolve.new(item_arg, func )
end

class BatchLoader
attr_reader :func, :args
def initialize(func, args)
@func = func
@args = args
end
end

class BatchResolve
attr_reader :item_arg, :func
def initialize(item_arg, func)
@item_arg = item_arg
@func = func
end
end

class Accumulator
def initialize
@storage = init_storage
end

def register(loader, group_args, frame, batch_resolve)
key = [loader, group_args]
callback = [frame, batch_resolve.func]
@storage[key][batch_resolve.item_arg] << callback
end

def any?
@storage.any?
end

def resolve_all(&block)
batches = @storage
@storage = init_storage
batches.each do |(loader, group_args), item_arg_callbacks|
item_args = item_arg_callbacks.keys
loader.call(*group_args, item_args) { |item_arg, result|
callbacks = item_arg_callbacks[item_arg]
callbacks.each do |(frame, func)|
next_result = func.nil? ? result : func.call(result)
yield(frame, next_result)
end
}
end
end

private

def init_storage
# { [loader, group_args] => { item_arg => [callback, ...] } }
Hash.new { |h, k| h[k] = Hash.new { |h2, k2| h2[k2] = [] } }
end
end
end
end
end
Loading