Method: GraphQL::Subscriptions::ActionCableSubscriptions#setup_stream
- Defined in:
- lib/graphql/subscriptions/action_cable_subscriptions.rb
#setup_stream(channel, initial_event) ⇒ Object
Every subscribing channel is listening here, but only one of them takes any action. This is so we can reuse payloads when possible, and make one payload to send to all subscribers.
But the problem is, any channel could close at any time, so each channel has to be ready to take over the primary position.
To make sure there's always one-and-only-one channel building payloads, let the listener belonging to the first event on the list be the one to build and publish payloads.
168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 |
# File 'lib/graphql/subscriptions/action_cable_subscriptions.rb', line 168 def setup_stream(channel, initial_event) topic = initial_event.topic event_stream = stream_event_name(initial_event) channel.stream_from(event_stream, coder: @action_cable_coder) do || events_by_fingerprint = @events[topic] object = nil events_by_fingerprint.each do |_fingerprint, events| if !events.empty? && events.first == initial_event # The fingerprint has told us that this response should be shared by all subscribers, # so just run it once, then deliver the result to every subscriber first_event = events.first first_subscription_id = first_event.context.fetch(:subscription_id) object ||= (, first_event.context) result = execute_update(first_subscription_id, first_event, object) if !result.nil? # Having calculated the result _once_, send the same payload to all subscribers events.each do |event| subscription_id = event.context.fetch(:subscription_id) deliver(subscription_id, result) end end end end nil end end |