class GraphQL::Schema::Subscription
This class can be extended to create fields on your subscription root.
It provides hooks for the different parts of the subscription lifecycle:
-
‘#authorized?`: called before initial subscription and subsequent updates
-
‘#subscribe`: called for the initial subscription
-
‘#update`: called for subsequent update
Also, ‘#unsubscribe` terminates the subscription.
Constants
- NO_UPDATE
- READING_SCOPE
Public Class Methods
GraphQL::Schema::Resolver::new
# File lib/graphql/schema/subscription.rb, line 22 def initialize(object:, context:, field:) super # Figure out whether this is an update or an initial subscription @mode = context.query.subscription_update? ? :update : :subscribe end
Call this method to provide a new subscription_scope
; OR call it without an argument to get the subscription_scope
@param new_scope [Symbol] @param optional [Boolean] If true, then don’t require ‘scope:` to be provided to updates to this subscription. @return [Symbol]
# File lib/graphql/schema/subscription.rb, line 108 def self.subscription_scope(new_scope = READING_SCOPE, optional: false) if new_scope != READING_SCOPE @subscription_scope = new_scope @subscription_scope_optional = optional elsif defined?(@subscription_scope) @subscription_scope else find_inherited_value(:subscription_scope) end end
# File lib/graphql/schema/subscription.rb, line 119 def self.subscription_scope_optional? if defined?(@subscription_scope_optional) @subscription_scope_optional else find_inherited_value(:subscription_scope_optional, false) end end
This is called during initial subscription to get a “name” for this subscription. Later, when ‘.trigger` is called, this will be called again to build another “name”. Any subscribers with matching topic will begin the update flow.
The default implementation creates a string using the field name, subscription scope, and argument keys and values. In that implementation, only ‘.trigger` calls with _exact matches_ result in updates to subscribers.
To implement a filtered stream-type subscription flow, override this method to return a string with field name and subscription scope. Then, implement {#update} to compare its arguments to the current ‘object` and return {NO_UPDATE} when an update should be filtered out.
@see {#update} for how to skip updates when an event comes with a matching topic. @param arguments [Hash<String => Object>] The arguments for this topic, in GraphQL-style (camelized strings) @param field [GraphQL::Schema::Field] @param scope [Object, nil] A value corresponding to ‘.trigger(… scope:)` (for updates) or the `subscription_scope` found in `context` (for initial subscriptions). @return [String] An identifier corresponding to a stream of updates
# File lib/graphql/schema/subscription.rb, line 143 def self.topic_for(arguments:, field:, scope:) Subscriptions::Serialize.dump_recursive([scope, field.graphql_name, arguments]) end
Public Instance Methods
If an argument is flagged with ‘loads:` and no object is found for it, remove this subscription (assuming that the object was deleted in the meantime, or that it became inaccessible).
# File lib/graphql/schema/subscription.rb, line 89 def load_application_object_failed(err) if @mode == :update unsubscribe end super end
Implement the {Resolve} API
# File lib/graphql/schema/subscription.rb, line 45 def resolve(**args) # Dispatch based on `@mode`, which will raise a `NoMethodError` if we ever # have an unexpected `@mode` public_send("resolve_#{@mode}", **args) end
Wrap the user-defined ‘#subscribe` hook
# File lib/graphql/schema/subscription.rb, line 52 def resolve_subscribe(**args) ret_val = args.any? ? subscribe(**args) : subscribe if ret_val == :no_response context.skip else ret_val end end
Wrap the user-provided ‘#update` hook
# File lib/graphql/schema/subscription.rb, line 69 def resolve_update(**args) ret_val = args.any? ? update(**args) : update if ret_val == NO_UPDATE context.namespace(:subscriptions)[:no_update] = true context.skip else ret_val end end
GraphQL::Schema::Resolver#resolve_with_support
# File lib/graphql/schema/subscription.rb, line 28 def resolve_with_support(**args) result = nil unsubscribed = true catch :graphql_subscription_unsubscribed do result = super unsubscribed = false end if unsubscribed context.skip else result end end
The default implementation returns nothing on subscribe. Override it to return an object or ‘:no_response` to (explicitly) return nothing.
# File lib/graphql/schema/subscription.rb, line 64 def subscribe(args = {}) :no_response end
Call this to halt execution and remove this subscription from the system
# File lib/graphql/schema/subscription.rb, line 97 def unsubscribe context.namespace(:subscriptions)[:unsubscribed] = true throw :graphql_subscription_unsubscribed end
The default implementation returns the root object. Override it to return {NO_UPDATE} if you want to skip updates sometimes. Or override it to return a different object.
# File lib/graphql/schema/subscription.rb, line 82 def update(args = {}) object end