diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/action_cable/channel/callbacks.rb | 4 | ||||
-rw-r--r-- | lib/action_cable/channel/periodic_timers.rb | 3 | ||||
-rw-r--r-- | lib/action_cable/channel/streams.rb | 47 |
3 files changed, 54 insertions, 0 deletions
diff --git a/lib/action_cable/channel/callbacks.rb b/lib/action_cable/channel/callbacks.rb index 9ca8896770..dcdd27b9a7 100644 --- a/lib/action_cable/channel/callbacks.rb +++ b/lib/action_cable/channel/callbacks.rb @@ -11,10 +11,14 @@ module ActionCable end module ClassMethods + # Name methods that should be called when the channel is subscribed to. + # (These methods should be private, so they're not callable by the user). def on_subscribe(*methods) self.on_subscribe_callbacks += methods end + # Name methods that should be called when the channel is unsubscribed from. + # (These methods should be private, so they're not callable by the user). def on_unsubscribe(*methods) self.on_unsubscribe_callbacks += methods end diff --git a/lib/action_cable/channel/periodic_timers.rb b/lib/action_cable/channel/periodic_timers.rb index 33b9ff19be..fea957563f 100644 --- a/lib/action_cable/channel/periodic_timers.rb +++ b/lib/action_cable/channel/periodic_timers.rb @@ -12,6 +12,9 @@ module ActionCable end module ClassMethods + # Allow you to call a private method <tt>every</tt> so often seconds. This periodic timer can be useful + # for sending a steady flow of updates to a client based off an object that was configured on subscription. + # It's an alternative to using streams if the channel is able to do the work internally. def periodically(callback, every:) self.periodic_timers += [ [ callback, every: every ] ] end diff --git a/lib/action_cable/channel/streams.rb b/lib/action_cable/channel/streams.rb index 9ff2f85fa1..6a3dc76c1d 100644 --- a/lib/action_cable/channel/streams.rb +++ b/lib/action_cable/channel/streams.rb @@ -1,5 +1,50 @@ module ActionCable module Channel + # Streams allow channels to route broadcastings to the subscriber. A broadcasting is an discussed elsewhere a pub/sub queue where any data + # put into it is automatically sent to the clients that are connected at that time. It's purely an online queue, though. If you're not + # streaming a broadcasting at the very moment it sends out an update, you'll not get that update when connecting later. + # + # Most commonly, the streamed broadcast is sent straight to the subscriber on the client-side. The channel just acts as a connector between + # the two parties (the broadcaster and the channel subscriber). Here's an example of a channel that allows subscribers to get all new + # comments on a given page: + # + # class CommentsChannel < ApplicationCable::Channel + # def follow(data) + # stream_from "comments_for_#{data['recording_id']}" + # end + # + # def unfollow + # stop_all_streams + # end + # end + # + # So the subscribers of this channel will get whatever data is put into the, let's say, `comments_for_45` broadcasting as soon as it's put there. + # That looks like so from that side of things: + # + # ActionCable.server.broadcast "comments_for_45", author: 'DHH', content: 'Rails is just swell' + # + # If you don't just want to parlay the broadcast unfiltered to the subscriber, you can supply a callback that let's you alter what goes out. + # Example below shows how you can use this to provide performance introspection in the process: + # + # class ChatChannel < ApplicationCable::Channel + # def subscribed + # @room = Chat::Room[params[:room_number]] + # + # stream_from @room.channel, -> (message) do + # message = ActiveSupport::JSON.decode(m) + # + # if message['originated_at'].present? + # elapsed_time = (Time.now.to_f - message['originated_at']).round(2) + # + # ActiveSupport::Notifications.instrument :performance, measurement: 'Chat.message_delay', value: elapsed_time, action: :timing + # logger.info "Message took #{elapsed_time}s to arrive" + # end + # + # transmit message + # end + # end + # + # You can stop streaming from all broadcasts by calling #stop_all_streams. module Streams extend ActiveSupport::Concern @@ -7,6 +52,8 @@ module ActionCable on_unsubscribe :stop_all_streams end + # Start streaming from the named <tt>broadcasting</tt> pubsub queue. Optionally, you can pass a <tt>callback</tt> that'll be used + # instead of the default of just transmitting the updates straight to the subscriber. def stream_from(broadcasting, callback = nil) callback ||= default_stream_callback(broadcasting) |