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?

Only analyze subscription operations
def analyze?
  @query.subscription?
end

def apply_broadcastable(field_defn)

Modify `@subscription_broadcastable` based on `field_defn`'s configuration (and/or the default value)
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

Returns:
  • (void) -
def result
  query.context.namespace(:subscriptions)[:subscription_broadcastable] = @subscription_broadcastable
  nil
end