Class: GraphQL::Subscriptions::ActionCableSubscriptions
- Inherits:
-
GraphQL::Subscriptions
- Object
- GraphQL::Subscriptions
- GraphQL::Subscriptions::ActionCableSubscriptions
- Defined in:
- lib/graphql/subscriptions/action_cable_subscriptions.rb
Overview
A subscriptions implementation that sends data as ActionCable broadcastings.
Experimental, some things to keep in mind:
- No queueing system; ActiveJob should be added
- Take care to reload context when re-delivering the subscription. (see Query#subscription_update?)
Constant Summary collapse
- SUBSCRIPTION_PREFIX =
"graphql-subscription:"
- EVENT_PREFIX =
"graphql-event:"
Instance Method Summary collapse
-
#delete_subscription(subscription_id) ⇒ Object
The channel was closed, forget about it.
-
#deliver(subscription_id, result) ⇒ Object
This subscription was re-evaluated.
-
#execute_all(event, object) ⇒ Object
An event was triggered; Push the data over ActionCable.
-
#initialize(serializer: Serialize, **rest) ⇒ ActionCableSubscriptions
constructor
A new instance of ActionCableSubscriptions.
-
#read_subscription(subscription_id) ⇒ Object
Return the query from “storage” (in memory).
-
#write_subscription(query, events) ⇒ Object
A query was run where these events were subscribed to.
Methods inherited from GraphQL::Subscriptions
#build_id, #each_subscription_id, #execute, #normalize_name, #trigger, use
Constructor Details
#initialize(serializer: Serialize, **rest) ⇒ ActionCableSubscriptions
Returns a new instance of ActionCableSubscriptions
88 89 90 91 92 93 94 |
# File 'lib/graphql/subscriptions/action_cable_subscriptions.rb', line 88 def initialize(serializer: Serialize, **rest) # A per-process map of subscriptions to deliver. # This is provided by Rails, so let's use it @subscriptions = Concurrent::Map.new @serializer = serializer super end |
Instance Method Details
#delete_subscription(subscription_id) ⇒ Object
The channel was closed, forget about it.
141 142 143 |
# File 'lib/graphql/subscriptions/action_cable_subscriptions.rb', line 141 def delete_subscription(subscription_id) @subscriptions.delete(subscription_id) end |
#deliver(subscription_id, result) ⇒ Object
This subscription was re-evaluated. Send it to the specific stream where this client was waiting.
106 107 108 109 |
# File 'lib/graphql/subscriptions/action_cable_subscriptions.rb', line 106 def deliver(subscription_id, result) payload = { result: result.to_h, more: true } ActionCable.server.broadcast(SUBSCRIPTION_PREFIX + subscription_id, payload) end |
#execute_all(event, object) ⇒ Object
An event was triggered; Push the data over ActionCable. Subscribers will re-evaluate locally.
98 99 100 101 102 |
# File 'lib/graphql/subscriptions/action_cable_subscriptions.rb', line 98 def execute_all(event, object) stream = EVENT_PREFIX + event.topic = @serializer.dump(object) ActionCable.server.broadcast(stream, ) end |
#read_subscription(subscription_id) ⇒ Object
Return the query from “storage” (in memory)
130 131 132 133 134 135 136 137 138 |
# File 'lib/graphql/subscriptions/action_cable_subscriptions.rb', line 130 def read_subscription(subscription_id) query = @subscriptions[subscription_id] { query_string: query.query_string, variables: query.provided_variables, context: query.context.to_h, operation_name: query.operation_name, } end |
#write_subscription(query, events) ⇒ Object
A query was run where these events were subscribed to. Store them in memory in this ActionCable frontend. It will receive notifications when events come in and re-evaluate the query locally.
115 116 117 118 119 120 121 122 123 124 125 126 127 |
# File 'lib/graphql/subscriptions/action_cable_subscriptions.rb', line 115 def write_subscription(query, events) channel = query.context.fetch(:channel) subscription_id = query.context[:subscription_id] ||= build_id stream = query.context[:action_cable_stream] ||= SUBSCRIPTION_PREFIX + subscription_id channel.stream_from(stream) @subscriptions[subscription_id] = query events.each do |event| channel.stream_from(EVENT_PREFIX + event.topic, coder: ActiveSupport::JSON) do || execute(subscription_id, event, @serializer.load()) nil end end end |