class GraphQL::Subscriptions::BroadcastAnalyzer
@see Subscriptions#broadcastable? for a public API
@api private
Assign the result to ‘context.namespace(:subscriptions)`
- Is completely broadcastable
- Is a subscription operation
Detect whether the current operation:
def analyze?
def analyze? @query.subscription? end
def apply_broadcastable(field_defn)
def apply_broadcastable(field_defn) current_field_broadcastable = field_defn.introspection? || field_defn.broadcastable? case current_field_broadcastable when nil # If the value wasn't set, mix in the default value: # - If the default is false and the current value is true, make it false # - If the default is true and the current value is true, it stays true # - If the default is false and the current value is false, keep it false # - If the default is true and the current value is false, keep it false @subscription_broadcastable = @subscription_broadcastable && @default_broadcastable when false # One non-broadcastable field is enough to make the whole subscription non-broadcastable @subscription_broadcastable = false when true # Leave `@broadcastable_query` true if it's already true, # but don't _set_ it to true if it was set to false by something else. # Actually, just leave it! else raise ArgumentError, "Unexpected `.broadcastable?` value for #{field_defn.path}: #{current_field_broadcastable}" end end
def initialize(subject)
def initialize(subject) super @default_broadcastable = subject.schema.subscriptions.default_broadcastable # Maybe this will get set to false while analyzing @subscription_broadcastable = true end
def on_enter_field(node, parent, visitor)
def on_enter_field(node, parent, visitor) if (@subscription_broadcastable == false) || visitor.skipping? return end current_field = visitor.field_definition apply_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 apply_broadcastable(ot_field) end end end end
def result
-
(void)
-
def result query.context.namespace(:subscriptions)[:subscription_broadcastable] = @subscription_broadcastable nil end