Skip to content

Instantly share code, notes, and snippets.

@rmosolgo
Last active August 1, 2023 18:13
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/94013c0640c4cc22d30a95d6896d1beb to your computer and use it in GitHub Desktop.
Save rmosolgo/94013c0640c4cc22d30a95d6896d1beb to your computer and use it in GitHub Desktop.
Parallel I/O with GraphQL::Dataloader
require "bundler/inline"
gemfile do
gem "graphql"
gem "libev_scheduler"
end
class MySchema < GraphQL::Schema
class FetchThings < GraphQL::Dataloader::Source
def initialize(starting_at:)
@starting_at = starting_at
end
def fetch(_ids)
# Pretend it takes a long time:
sleep_for = [0.5, 1].sample
sleep sleep_for
# Return the things:
things = 4.times.map do |i|
{ value: @starting_at + i }
end
# There's only ever one ID here, but return an Array to make it match:
[ things ]
end
end
class Thing < GraphQL::Schema::Object
field :value, Int
end
class Query < GraphQL::Schema::Object
field :things, [Thing] do
argument :starting_at, Int
end
def things(starting_at:)
dataloader.with(FetchThings, starting_at: starting_at).load(nil)
end
end
query(Query)
use GraphQL::Dataloader, nonblocking: true
end
Fiber.set_scheduler(Libev::Scheduler.new)
def run_query
start = Time.now
pp MySchema.execute("{
t1: things(startingAt: 0) { value }
t2: things(startingAt: 4) { value }
}").to_h
# {"data"=>
# {"t1"=>[{"value"=>0}, {"value"=>1}, {"value"=>2}, {"value"=>3}],
# "t2"=>[{"value"=>4}, {"value"=>5}, {"value"=>6}, {"value"=>7}]}
# }
pp [:elapsed, Time.now - start, :seconds]
# [:elapsed, 1.006262, :seconds]
# It only took one second -- the two sleeps happened simultaneously
end
10.times do
run_query
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment