class GraphQL::Dataloader::Source
Constants
- MAX_ITERATIONS
Attributes
Public Class Methods
# File lib/graphql/dataloader/source.rb, line 254 def self.batch_key_for(*batch_args, **batch_kwargs) if batch_kwargs.any? # rubocop:disable Development/NoneWithoutBlockCop [*batch_args, **batch_kwargs] else batch_args end end
These arguments are given to dataloader.with(source_class, ...). The object returned from this method is used to de-duplicate batch loads under the hood by using it as a Hash key.
By default, the arguments are all put in an Array. To customize how this source’s batches are merged, override this method to return something else.
For example, if you pass ActiveRecord::Relations to .with(...), you could override this method to call .to_sql on them, thus merging .load(...) calls when they apply to equivalent relations.
Parameters
-
batch_args(Array<Object>) -
batch_kwargs(Hash)
Returns
-
Object
Public Instance Methods
Source
# File lib/graphql/dataloader/source.rb, line 270 def clear_cache @results.clear nil end
Clear any already-loaded objects for this source
Returns
-
void
# File lib/graphql/dataloader/source.rb, line 145 def fetch(keys) # somehow retrieve these from the backend raise "Implement `#{self.class}#fetch(#{keys.inspect}) to return a record for each of the keys" end
Subclasses must implement this method to return a value for each of keys
Parameters
-
keys(Array<Object>) — keys passed to load, load all, request, or request all
Returns
-
Array<Object>— A loaded value for each ofkeys. The array must match one-for-one to the list ofkeys.
Source
# File lib/graphql/dataloader/source.rb, line 93 def load(value) result_key = result_key_for(value) if @results.key?(result_key) result_for(result_key) else add_pending_key(result_key, value) sync([result_key]) result_for(result_key) end end
# File lib/graphql/dataloader/source.rb, line 114 def load_all(values) result_keys = [] pending_keys = [] values.each { |v| k = result_key_for(v) result_keys << k if add_pending_key(k, v) pending_keys << k end } if !pending_keys.empty? sync(pending_keys) end result_keys.map! { |k| result_for(k) } result_keys end
# File lib/graphql/dataloader/source.rb, line 197 def merge(new_results) new_results.each do |new_k, new_v| key = result_key_for(new_k) @results[key] = new_v end nil end
Add these key-value pairs to this source’s cache (future loads will use these merged values).
Parameters
-
new_results(Hash<Object => Object>) — key-value pairs to cache in this source
Returns
-
void
# File lib/graphql/dataloader/source.rb, line 65 def normalize_fetch_key(value) value end
Implement this method if varying values given to load (etc) should be consolidated or normalized before being handed off to your fetch implementation.
This is different than result_key_for because that method handles unification inside Dataloader’s cache, but this method changes the value passed into fetch.
Parameters
-
value(Object) — The value passed toload,load_all,request, orrequest_all
Returns
-
Object— The value given tofetch
Source
# File lib/graphql/dataloader/source.rb, line 180 def pending? !@pending.empty? end
Returns
-
Boolean— True if this source has any pending requests for data.
# File lib/graphql/dataloader/source.rb, line 26 def request(value) res_key = result_key_for(value) add_pending_key(res_key, value) Dataloader::Request.new(self, value) end
Returns
-
Dataloader::Request— a pending request for a value fromkey. Call.loadon that object to wait for the result.
# File lib/graphql/dataloader/source.rb, line 75 def request_all(values) values.each do |v| res_key = result_key_for(v) add_pending_key(res_key, v) end Dataloader::RequestAll.new(self, values) end
Returns
-
Dataloader::Request— a pending request for a values fromkeys. Call.loadon that object to wait for the results.
# File lib/graphql/dataloader/source.rb, line 45 def result_key_for(value) value end
Implement this method to return a stable identifier if different key objects should load the same data value.
Parameters
-
value(Object) — A value passed to.requestor.load, for which a value will be loaded
Returns
-
Object— The key for tracking this pending data
# File lib/graphql/dataloader/source.rb, line 160 def sync(pending_result_keys) @dataloader.queue_pending_source(self) if pending? @dataloader.yield(self) iterations = 0 while pending_result_keys.any? { |key| !@results.key?(key) } iterations += 1 if iterations > MAX_ITERATIONS raise "#{self.class}#sync tried #{MAX_ITERATIONS} times to load pending keys (#{pending_result_keys}), but they still weren't loaded. There is likely a circular dependency#{@dataloader.fiber_limit ? " or `fiber_limit: #{@dataloader.fiber_limit}` is set too low" : ""}." end @dataloader.yield(self) end nil end
Wait for a batch, if there’s anything to batch. Then run the batch and update the cache.
Returns
-
void