class GraphQL::Streaming::ActionCableCollector

Accept patches from GraphQL and send them to clients via `channel_name`.

Patches are also issued with `query_id`. This way, clients on the same channel can tell whether a patch is for their query or someone else's.

When a query is finished (no more patches will be sent), the collector can notify clients with {#close}

@example Sending patches over ActionCable

# Use this middleware to close queries when they're finished:
MySchema.middleware << GraphQL::Streaming::ActionCableMiddleware.new

class GraphqlChannel < ApplicationCable::Channel
  # Implement `#fetch(data)`, which corresponds with GraphQLCable client
  def fetch(data)
    query_string = data["query"]
    variables = ensure_hash(data["variables"] || {})

    # build a collector including `query_id`
    # which comes from GraphQLCable client
    broadcaster = ActionCable.server.broadcaster_for(channel_name)
    query_id = query_id = data["query_id"]
    collector = GraphQL::Streaming::ActionCableCollector.new(query_id, broadcaster)

    context = { collector: collector }
    Schema.execute(query_string, variables: variables, context: context)
  end
end

@example Tell the client to stop listening for patches

collector = GraphQL::Streaming::ActionCableCollector.new(query_id, broadcaster)
# ...
collector.close

Public Class Methods

new(channel, query_id) click to toggle source

@param [String] A unique identifier for this query (probably provided by the client) @param [ActionCable::Server::Broadcasting::Broadcaster] The broadcast target for GraphQL's patches

# File lib/graphql/streaming/action_cable_collector.rb, line 41
def initialize(channel, query_id)
  @query_id = query_id
  @channel = channel
  @closed = false
end

Public Instance Methods

close() click to toggle source

Broadcast a message to terminate listeners on this query @return [void]

# File lib/graphql/streaming/action_cable_collector.rb, line 64
def close
  @channel.send_graphql_payload({
    query_id: @query_id,
    close: true,
  })
  @closed = true
end
patch(path:, value:) click to toggle source

Implements the “collector” API for DeferredExecution. Sends `{patch: {…}, query_id: @query_id}` over `@broadcaster`. @return [void]

# File lib/graphql/streaming/action_cable_collector.rb, line 50
def patch(path:, value:)
  if !@closed
    @channel.send_graphql_payload({
      query_id: @query_id,
      patch: {
        path: path,
        value: value,
      },
    })
  end
end