-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Open
Description
Currently @stream will defer child selections on list items, but all items are enumerated before any child selections are run.
A better workflow might be that, when a @streamed list is resolved, there's no call to .each right away. Instead, and empty list is put in the response, and then each deferral gets the item it needs and resolves its subfields.
Here's a script to demonstrate the behavior in question:
`@stream` with lazy enumeration
require "bundler/inline"
gemfile do
gem "graphql", path: "./" # "~>2.2.0"
gem "graphql-pro", "~>1.0"
end
class MySchema < GraphQL::Schema
class LazyItems
DATA = [
OpenStruct.new(name: "Stopwatch"),
OpenStruct.new(name: "Necktie"),
OpenStruct.new(name: "Suitcase"),
OpenStruct.new(name: "Chopstick"),
OpenStruct.new(name: "Peanut"),
OpenStruct.new(name: "Screwdriver"),
]
def each
idx = 0
while idx < DATA.length
item = DATA[idx]
puts "Yielding #{idx}: #{item.name}"
yield(item)
idx += 1
end
self
end
end
class Item < GraphQL::Schema::Object
field :name, String
def name
puts "Resolving Item#name: #{object.name}"
object.name
end
end
class Query < GraphQL::Schema::Object
field :items, [Item]
def items
puts "Resolving items"
LazyItems.new
end
end
query(Query)
use GraphQL::Pro::Stream
end
query_str = "{ items @stream { name } }"
res = MySchema.execute(query_str)
res.context[:defer].each do |deferral|
deferral.to_h
end
pp res.to_hIt should alternate between yield and resolve messages, but instead, it does all the yields then all the resolves.
If the implementation supported lazy enumeration, then you could use @stream to break up database requests into smaller chunks using a cursor.
trumbitta and tgwizard
Metadata
Metadata
Assignees
Labels
No labels