Created
December 25, 2020 18:50
-
-
Save rmosolgo/55ec9c6739db3e348fb6aeb99377b128 to your computer and use it in GitHub Desktop.
fiber_batch_loader.rb
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 "fiber" | |
# Set up a pretend database | |
DATA = { | |
1 => "Hannah Coulter", | |
2 => "Jayber Crow", | |
3 => "That Distant Land" | |
} | |
# This loader will fetch items in batches of IDs | |
class Loader | |
def initialize | |
@ids = [] | |
@data = {} | |
end | |
def load(id) | |
p "Adding #{id}" | |
@ids << id | |
Fiber.yield | |
# Assumes that any batchable IDs will be added to this loader in the interim | |
sync | |
@data[id] | |
end | |
def sync | |
if @ids.any? | |
p "syncing #{@ids}" | |
@ids.each { |id| @data[id] = DATA[id] } | |
@ids = [] | |
end | |
end | |
end | |
LOADER = Loader.new | |
def load_book(id:) | |
# The important thing here is that the batch loading is completely hidden | |
title = LOADER.load(id) | |
title.upcase | |
end | |
# This is the pretend GraphQL-Ruby runtime: | |
results = [nil, nil, nil] | |
# {path, fiber} tuples | |
fields = [ | |
[0, Fiber.new { load_book(id: 1) }], | |
[1, Fiber.new { load_book(id: 2) }], | |
[2, Fiber.new { load_book(id: 3) }], | |
] | |
while ((idx, f) = fields.shift) && (f.alive?) | |
res = f.resume | |
if f.alive? | |
fields << [idx, f] | |
else | |
results[idx] = res | |
end | |
end | |
pp results | |
# % ruby fiber_test.rb | |
# "Adding 1" | |
# "Adding 2" | |
# "Adding 3" | |
# "syncing [1, 2, 3]" | |
# ["HANNAH COULTER", "JAYBER CROW", "THAT DISTANT LAND"] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment