Class: GraphQL::Subscriptions

Inherits:
Object
  • Object
show all
Defined in:
lib/graphql/subscriptions.rb,
lib/graphql/subscriptions/event.rb,
lib/graphql/subscriptions/serialize.rb,
lib/graphql/subscriptions/instrumentation.rb,
lib/graphql/subscriptions/action_cable_subscriptions.rb

Direct Known Subclasses

ActionCableSubscriptions

Defined Under Namespace

Modules: Serialize Classes: ActionCableSubscriptions, Event, Instrumentation, InvalidTriggerError

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(schema:, **rest) ⇒ Subscriptions

Returns a new instance of Subscriptions

Parameters:

  • schema (Class)

    the GraphQL schema this manager belongs to



30
31
32
# File 'lib/graphql/subscriptions.rb', line 30

def initialize(schema:, **rest)
  @schema = schema
end

Class Method Details

.use(defn, options = {}) ⇒ Object

See Also:

  • for options, concrete implementations may add options.


19
20
21
22
23
24
25
26
27
# File 'lib/graphql/subscriptions.rb', line 19

def self.use(defn, options = {})
  schema = defn.target
  options[:schema] = schema
  schema.subscriptions = self.new(options)
  instrumentation = Subscriptions::Instrumentation.new(schema: schema)
  defn.instrument(:field, instrumentation)
  defn.instrument(:query, instrumentation)
  nil
end

Instance Method Details

#build_idString

Returns A new unique identifier for a subscription

Returns:

  • (String)

    A new unique identifier for a subscription



151
152
153
# File 'lib/graphql/subscriptions.rb', line 151

def build_id
  SecureRandom.uuid
end

#deliver(subscription_id, result, context) ⇒ void

This method returns an undefined value.

A subscription query was re-evaluated, returning result. The result should be send to subscription_id.

Parameters:

Raises:

  • (NotImplementedError)


137
138
139
# File 'lib/graphql/subscriptions.rb', line 137

def deliver(subscription_id, result, context)
  raise NotImplementedError
end

#each_subscription_id(event) {|subscription_id| ... } ⇒ void

This method returns an undefined value.

Get each subscription_id subscribed to event.topic and yield them

Parameters:

Yield Parameters:

  • subscription_id (String)

Raises:

  • (NotImplementedError)


119
120
121
# File 'lib/graphql/subscriptions.rb', line 119

def each_subscription_id(event)
  raise NotImplementedError
end

#execute(subscription_id, event, object) ⇒ void

This method returns an undefined value.

event was triggered on object, and subscription_id was subscribed, so it should be updated.

Load subscription_id’s GraphQL data, re-evaluate the query, and deliver the result.

This is where a queue may be inserted to push updates in the background.

Parameters:

  • subscription_id (String)
  • event (GraphQL::Subscriptions::Event)

    The event which was triggered

  • object (Object)

    The value for the subscription field



82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/graphql/subscriptions.rb', line 82

def execute(subscription_id, event, object)
  # Lookup the saved data for this subscription
  query_data = read_subscription(subscription_id)
  # Fetch the required keys from the saved data
  query_string = query_data.fetch(:query_string)
  variables = query_data.fetch(:variables)
  context = query_data.fetch(:context)
  operation_name = query_data.fetch(:operation_name)
  # Re-evaluate the saved query
  result = @schema.execute(
    {
      query: query_string,
      context: context,
      subscription_topic: event.topic,
      operation_name: operation_name,
      variables: variables,
      root_value: object,
    }
  )
  deliver(subscription_id, result)
end

#execute_all(event, object) ⇒ void

This method returns an undefined value.

Event event occurred on object, Update all subscribers.

Parameters:



109
110
111
112
113
# File 'lib/graphql/subscriptions.rb', line 109

def execute_all(event, object)
  each_subscription_id(event) do |subscription_id|
    execute(subscription_id, event, object)
  end
end

#normalize_name(event_or_arg_name) ⇒ String

Convert a user-provided event name or argument to the equivalent in GraphQL.

By default, it converts the identifier to camelcase. Override this in a subclass to change the transformation.

Parameters:

  • event_or_arg_name (String, Symbol)

Returns:

  • (String)


163
164
165
# File 'lib/graphql/subscriptions.rb', line 163

def normalize_name(event_or_arg_name)
  Schema::Member::BuildType.camelize(event_or_arg_name.to_s)
end

#read_subscription(subscription_id) ⇒ Hash

The system wants to send an update to this subscription. Read its data and return it.

Parameters:

  • subscription_id (String)

Returns:

  • (Hash)

    Containing required keys

Raises:

  • (NotImplementedError)


127
128
129
# File 'lib/graphql/subscriptions.rb', line 127

def read_subscription(subscription_id)
  raise NotImplementedError
end

#trigger(event_name, args, object, scope: nil) ⇒ void

This method returns an undefined value.

Fetch subscriptions matching this field + arguments pair And pass them off to the queue.

Parameters:

  • event_name (String)
  • args (Hash<String, Symbol => Object])

    rgs [Hash<String, Symbol => Object]

  • object (Object)
  • scope (Symbol, String)


41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/graphql/subscriptions.rb', line 41

def trigger(event_name, args, object, scope: nil)
  event_name = event_name.to_s

  # Try with the verbatim input first:
  field = @schema.get_field("Subscription", event_name)

  if field.nil?
    # And if it wasn't found, normalize it:
    normalized_event_name = normalize_name(event_name)
    field = @schema.get_field("Subscription", normalized_event_name)
    if field.nil?
      raise InvalidTriggerError, "No subscription matching trigger: #{event_name} (looked for #{@schema.subscription.graphql_name}.#{normalized_event_name})"
    end
  else
    # Since we found a field, the original input was already normalized
    normalized_event_name = event_name
  end

  # Normalize symbol-keyed args to strings, try camelizing them
  normalized_args = normalize_arguments(normalized_event_name, field, args)

  event = Subscriptions::Event.new(
    name: normalized_event_name,
    arguments: normalized_args,
    field: field,
    scope: scope,
  )
  execute_all(event, object)
end

#write_subscription(query, events) ⇒ void

This method returns an undefined value.

query was executed and found subscriptions to events. Update the database to reflect this new state.

Parameters:

Raises:

  • (NotImplementedError)


146
147
148
# File 'lib/graphql/subscriptions.rb', line 146

def write_subscription(query, events)
  raise NotImplementedError
end