Last active
August 1, 2023 18:13
-
-
Save rmosolgo/94013c0640c4cc22d30a95d6896d1beb to your computer and use it in GitHub Desktop.
Parallel I/O with GraphQL::Dataloader
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 "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