class GraphQL::Batch::Loader
Attributes
executor[RW]
loader_key[RW]
Public Class Methods
for(*group_args)
click to toggle source
# File lib/graphql/batch/loader.rb, line 11 def self.for(*group_args) current_executor.loader(loader_key_for(*group_args)) { new(*group_args) } end
load(key)
click to toggle source
# File lib/graphql/batch/loader.rb, line 20 def self.load(key) self.for.load(key) end
load_many(keys)
click to toggle source
# File lib/graphql/batch/loader.rb, line 24 def self.load_many(keys) self.for.load_many(keys) end
loader_key_for(*group_args, **group_kwargs)
click to toggle source
# File lib/graphql/batch/loader.rb, line 16 def self.loader_key_for(*group_args, **group_kwargs) [self, group_kwargs, group_args] end
new()
click to toggle source
# File lib/graphql/batch/loader.rb, line 47 def initialize @loader_key = nil @executor = nil @queue = nil @cache = nil end
Private Class Methods
current_executor()
click to toggle source
# File lib/graphql/batch/loader.rb, line 31 def current_executor executor = Executor.current unless executor raise GraphQL::Batch::NoExecutorError, 'Cannot create loader without'\ ' an Executor. Wrap the call to `for` with `GraphQL::Batch.batch`'\ ' or use `GraphQL::Batch::SetupMultiplex` as a query instrumenter if'\ ' using with `graphql-ruby`' end executor end
Public Instance Methods
around_perform() { || ... }
click to toggle source
Interface to add custom code for purposes such as instrumenting the performance of the loader.
# File lib/graphql/batch/loader.rb, line 84 def around_perform yield end
load(key)
click to toggle source
# File lib/graphql/batch/loader.rb, line 54 def load(key) cache[cache_key(key)] ||= begin queue << key ::Promise.new.tap { |promise| promise.source = self } end end
load_many(keys)
click to toggle source
# File lib/graphql/batch/loader.rb, line 61 def load_many(keys) ::Promise.all(keys.map { |key| load(key) }) end
prime(key, value)
click to toggle source
# File lib/graphql/batch/loader.rb, line 65 def prime(key, value) cache[cache_key(key)] ||= ::Promise.resolve(value).tap { |p| p.source = self } end
resolved?()
click to toggle source
# File lib/graphql/batch/loader.rb, line 97 def resolved? @queue.nil? || @queue.empty? end
Protected Instance Methods
cache_key(load_key)
click to toggle source
Override to use a different key for the cache than the load key
# File lib/graphql/batch/loader.rb, line 135 def cache_key(load_key) load_key end
fulfill(key, value)
click to toggle source
Fulfill the key with provided value, for use in perform
# File lib/graphql/batch/loader.rb, line 104 def fulfill(key, value) finish_resolve(key) do |promise| promise.fulfill(value) end end
fulfilled?(key)
click to toggle source
Returns true when the key has already been fulfilled, otherwise returns false
# File lib/graphql/batch/loader.rb, line 117 def fulfilled?(key) promise = promise_for(key) # When a promise is fulfilled through this class, it will either: # become fulfilled, if fulfilled with a literal value # become pending with a new source if fulfilled with a promise # Either of these is acceptable, promise.rb will automatically re-wait # on the new source promise as needed. return true if promise.fulfilled? promise.pending? && promise.source != self end
perform(keys)
click to toggle source
Must override to load the keys and call fulfill
for each key
# File lib/graphql/batch/loader.rb, line 130 def perform(keys) raise NotImplementedError end
reject(key, reason)
click to toggle source
# File lib/graphql/batch/loader.rb, line 110 def reject(key, reason) finish_resolve(key) do |promise| promise.reject(reason) end end
Private Instance Methods
cache()
click to toggle source
# File lib/graphql/batch/loader.rb, line 149 def cache @cache ||= {} end
check_for_broken_promises(load_keys)
click to toggle source
# File lib/graphql/batch/loader.rb, line 169 def check_for_broken_promises(load_keys) load_keys.each do |key| promise = promise_for(key) # When a promise is fulfilled through this class, it will either: # become not pending, if fulfilled with a literal value # become pending with a new source if fulfilled with a promise # Either of these is acceptable, promise.rb will automatically re-wait # on the new source promise as needed. next unless promise.pending? && promise.source == self reject(key, ::Promise::BrokenError.new("#{self.class} didn't fulfill promise for key #{key.inspect}")) end end
finish_resolve(key) { |promise| ... }
click to toggle source
# File lib/graphql/batch/loader.rb, line 141 def finish_resolve(key) promise = promise_for(key) return yield(promise) unless executor executor.around_promise_callbacks do yield promise end end
promise_for(load_key)
click to toggle source
# File lib/graphql/batch/loader.rb, line 157 def promise_for(load_key) cache.fetch(cache_key(load_key)) end
queue()
click to toggle source
# File lib/graphql/batch/loader.rb, line 153 def queue @queue ||= [] end
reject_pending_promises(load_keys, err)
click to toggle source
# File lib/graphql/batch/loader.rb, line 161 def reject_pending_promises(load_keys, err) load_keys.each do |key| next unless promise_for(key).pending? reject(key, err) end end