Skip to content

Instantly share code, notes, and snippets.

@rmosolgo
Created April 18, 2024 18:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rmosolgo/4bef3d260656f6f43c324c94e8749d6f to your computer and use it in GitHub Desktop.
Save rmosolgo/4bef3d260656f6f43c324c94e8749d6f to your computer and use it in GitHub Desktop.
A query analyzer for debugging the broadcastability of GraphQL-Ruby subscriptions
require "bundler/inline"
gemfile do
gem "graphql", path: "./" # "2.3.0"
end
class MySchema < GraphQL::Schema
class SubThing < GraphQL::Schema::Object
field :name, String, broadcastable: true
field :viewer_can_edit, Boolean # not broadcastable
end
class Thing < GraphQL::Schema::Object
field :name, String, broadcastable: true
field :sub_thing, SubThing, broadcastable: true
end
class Subscription < GraphQL::Schema::Object
field :thing_updated, Thing, broadcastable: true
end
subscription(Subscription)
use GraphQL::Subscriptions, broadcast: true, default_broadcastable: false
class BroadcastDebugAnalyzer < GraphQL::Analysis::AST::Analyzer
def on_enter_field(node, parent, visitor)
if visitor.skipping?
return
end
current_field = visitor.field_definition
check_broadcastable(current_field)
current_type = visitor.parent_type_definition
if current_type.kind.interface?
pt = @query.possible_types(current_type)
pt.each do |object_type|
ot_field = @query.get_field(object_type, current_field.graphql_name)
# Inherited fields would be exactly the same object;
# only check fields that are overrides of the inherited one
if ot_field && ot_field != current_field
check_broadcastable(ot_field)
end
end
end
end
def check_broadcastable(field_defn)
field_broadcastable = field_defn.introspection? || field_defn.broadcastable?
if !field_broadcastable
puts "Not broadcastable: #{field_defn.path}"
end
end
def result
nil
end
end
query_analyzer(MySchema::BroadcastDebugAnalyzer)
end
puts MySchema.subscriptions.broadcastable?("subscription { thingUpdated { name subThing { name } } }").inspect
# => true
#
puts MySchema.subscriptions.broadcastable?("subscription { thingUpdated { name subThing { name viewerCanEdit } } }").inspect
# Not broadcastable: SubThing.viewerCanEdit
# => false
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment