Skip to content

Support Lazy Enumerators with Stream #4907

@rmosolgo

Description

@rmosolgo

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_h

It 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions