Skip to content

Instantly share code, notes, and snippets.

@rmosolgo
Last active December 6, 2023 14:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rmosolgo/2c9d5f87c0dfdbdeb68dae93e1742549 to your computer and use it in GitHub Desktop.
Save rmosolgo/2c9d5f87c0dfdbdeb68dae93e1742549 to your computer and use it in GitHub Desktop.
Parallel Dataloader Execution in GraphQL-Ruby
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