Last active
December 6, 2023 14:43
-
-
Save rmosolgo/2c9d5f87c0dfdbdeb68dae93e1742549 to your computer and use it in GitHub Desktop.
Parallel Dataloader Execution in GraphQL-Ruby
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require "bundler/inline" | |
gemfile do | |
gem "graphql" | |
gem "concurrent-ruby" | |
end | |
class MySchema < GraphQL::Schema | |
# This source assumes that each record requires an expensive database query of its *own*. | |
# If that's not the case, then remove `def initialize` below | |
# and use the `ids` passed to `def fetch` instead. | |
class IndependentRecordSource < GraphQL::Dataloader::Source | |
# Passing an ID here will tell GraphQL-Ruby to use a new Source instance for each ID | |
def initialize(id) | |
@id = id | |
end | |
# This method won't use `_ids` because it's actually _splitting_ work | |
# based on the `id` given to `initialize(...)`. | |
def fetch(_ids) | |
# Spin up the work in a background thread: | |
future = Concurrent::Future.execute do | |
puts "Sleeping... #{@id}" | |
sleep 1 | |
puts "Returning... #{@id}" | |
[{ id: @id }] | |
end | |
# Tell the dataloader to try doing other work: | |
dataloader.yield | |
# When the dataloader returns to this method, | |
# it will have done everything else it can. | |
# It's time to block and wait for a result: | |
future.value! | |
end | |
end | |
class Thing < GraphQL::Schema::Object | |
field :id, ID | |
end | |
class Query < GraphQL::Schema::Object | |
field :thing, Thing do | |
argument :id, ID | |
end | |
def thing(id:) | |
dataloader.with(IndependentRecordSource, id).load(:__nothing) | |
end | |
end | |
query(Query) | |
use GraphQL::Dataloader | |
end | |
puts "[#{Time.now.to_i}] start" | |
res = MySchema.execute <<-GRAPHQL | |
{ | |
t1: thing(id: "1") { id } | |
t2: thing(id: "2") { id } | |
t3: thing(id: "3") { id } | |
} | |
GRAPHQL | |
pp res.to_h | |
puts "[#{Time.now.to_i}] end" | |
# [1701873806] start | |
# Sleeping... 1 | |
# Sleeping... 2 | |
# Sleeping... 3 | |
# Returning... 1 | |
# Returning... 2 | |
# Returning... 3 | |
# {"data"=>{"t1"=>{"id"=>"1"}, "t2"=>{"id"=>"2"}, "t3"=>{"id"=>"3"}}} | |
# [1701873807] end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment