actioncable 7.1.5.1 → 7.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +40 -125
- data/README.md +1 -1
- data/app/assets/javascripts/action_cable.js +3 -3
- data/app/assets/javascripts/actioncable.esm.js +3 -3
- data/app/assets/javascripts/actioncable.js +3 -3
- data/lib/action_cable/channel/base.rb +104 -86
- data/lib/action_cable/channel/broadcasting.rb +25 -18
- data/lib/action_cable/channel/callbacks.rb +27 -25
- data/lib/action_cable/channel/naming.rb +9 -8
- data/lib/action_cable/channel/periodic_timers.rb +7 -7
- data/lib/action_cable/channel/streams.rb +79 -64
- data/lib/action_cable/channel/test_case.rb +112 -86
- data/lib/action_cable/connection/authorization.rb +4 -1
- data/lib/action_cable/connection/base.rb +53 -38
- data/lib/action_cable/connection/callbacks.rb +20 -18
- data/lib/action_cable/connection/client_socket.rb +3 -1
- data/lib/action_cable/connection/identification.rb +9 -5
- data/lib/action_cable/connection/internal_channel.rb +5 -2
- data/lib/action_cable/connection/message_buffer.rb +4 -1
- data/lib/action_cable/connection/stream.rb +2 -0
- data/lib/action_cable/connection/stream_event_loop.rb +4 -3
- data/lib/action_cable/connection/subscriptions.rb +6 -3
- data/lib/action_cable/connection/tagged_logger_proxy.rb +7 -4
- data/lib/action_cable/connection/test_case.rb +66 -59
- data/lib/action_cable/connection/web_socket.rb +10 -8
- data/lib/action_cable/deprecator.rb +2 -0
- data/lib/action_cable/engine.rb +5 -3
- data/lib/action_cable/gem_version.rb +6 -4
- data/lib/action_cable/helpers/action_cable_helper.rb +21 -19
- data/lib/action_cable/remote_connections.rb +19 -16
- data/lib/action_cable/server/base.rb +27 -15
- data/lib/action_cable/server/broadcasting.rb +23 -17
- data/lib/action_cable/server/configuration.rb +17 -14
- data/lib/action_cable/server/connections.rb +11 -5
- data/lib/action_cable/server/worker/active_record_connection_management.rb +2 -0
- data/lib/action_cable/server/worker.rb +4 -2
- data/lib/action_cable/subscription_adapter/async.rb +2 -0
- data/lib/action_cable/subscription_adapter/base.rb +2 -0
- data/lib/action_cable/subscription_adapter/channel_prefix.rb +2 -0
- data/lib/action_cable/subscription_adapter/inline.rb +2 -0
- data/lib/action_cable/subscription_adapter/postgresql.rb +7 -6
- data/lib/action_cable/subscription_adapter/redis.rb +13 -5
- data/lib/action_cable/subscription_adapter/subscriber_map.rb +2 -0
- data/lib/action_cable/subscription_adapter/test.rb +8 -5
- data/lib/action_cable/test_case.rb +2 -0
- data/lib/action_cable/test_helper.rb +51 -48
- data/lib/action_cable/version.rb +3 -1
- data/lib/action_cable.rb +12 -6
- data/lib/rails/generators/channel/channel_generator.rb +4 -2
- data/lib/rails/generators/test_unit/channel_generator.rb +2 -0
- metadata +13 -16
- /data/lib/rails/generators/channel/templates/application_cable/{channel.rb → channel.rb.tt} +0 -0
- /data/lib/rails/generators/channel/templates/application_cable/{connection.rb → connection.rb.tt} +0 -0
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
# :markup: markdown
|
|
4
|
+
|
|
3
5
|
require "active_support/core_ext/object/to_param"
|
|
4
6
|
|
|
5
7
|
module ActionCable
|
|
@@ -7,36 +9,41 @@ module ActionCable
|
|
|
7
9
|
module Broadcasting
|
|
8
10
|
extend ActiveSupport::Concern
|
|
9
11
|
|
|
10
|
-
included do
|
|
11
|
-
delegate :broadcasting_for, :broadcast_to, to: :class
|
|
12
|
-
end
|
|
13
|
-
|
|
14
12
|
module ClassMethods
|
|
15
|
-
# Broadcast a hash to a unique broadcasting for this
|
|
13
|
+
# Broadcast a hash to a unique broadcasting for this `model` in this channel.
|
|
16
14
|
def broadcast_to(model, message)
|
|
17
15
|
ActionCable.server.broadcast(broadcasting_for(model), message)
|
|
18
16
|
end
|
|
19
17
|
|
|
20
|
-
# Returns a unique broadcasting identifier for this
|
|
18
|
+
# Returns a unique broadcasting identifier for this `model` in this channel:
|
|
21
19
|
#
|
|
22
|
-
#
|
|
20
|
+
# CommentsChannel.broadcasting_for("all") # => "comments:all"
|
|
23
21
|
#
|
|
24
|
-
# You can pass any object as a target (e.g. Active Record model), and it
|
|
25
|
-
#
|
|
22
|
+
# You can pass any object as a target (e.g. Active Record model), and it would
|
|
23
|
+
# be serialized into a string under the hood.
|
|
26
24
|
def broadcasting_for(model)
|
|
27
25
|
serialize_broadcasting([ channel_name, model ])
|
|
28
26
|
end
|
|
29
27
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
object.
|
|
34
|
-
|
|
35
|
-
object.to_gid_param
|
|
36
|
-
|
|
37
|
-
|
|
28
|
+
private
|
|
29
|
+
def serialize_broadcasting(object) # :nodoc:
|
|
30
|
+
case
|
|
31
|
+
when object.is_a?(Array)
|
|
32
|
+
object.map { |m| serialize_broadcasting(m) }.join(":")
|
|
33
|
+
when object.respond_to?(:to_gid_param)
|
|
34
|
+
object.to_gid_param
|
|
35
|
+
else
|
|
36
|
+
object.to_param
|
|
37
|
+
end
|
|
38
38
|
end
|
|
39
|
-
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def broadcasting_for(model)
|
|
42
|
+
self.class.broadcasting_for(model)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def broadcast_to(model, message)
|
|
46
|
+
self.class.broadcast_to(model, message)
|
|
40
47
|
end
|
|
41
48
|
end
|
|
42
49
|
end
|
|
@@ -1,36 +1,39 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
# :markup: markdown
|
|
4
|
+
|
|
3
5
|
require "active_support/callbacks"
|
|
4
6
|
|
|
5
7
|
module ActionCable
|
|
6
8
|
module Channel
|
|
7
|
-
#
|
|
9
|
+
# # Action Cable Channel Callbacks
|
|
10
|
+
#
|
|
11
|
+
# Action Cable Channel provides callback hooks that are invoked during the life
|
|
12
|
+
# cycle of a channel:
|
|
8
13
|
#
|
|
9
|
-
#
|
|
10
|
-
#
|
|
14
|
+
# * [before_subscribe](rdoc-ref:ClassMethods#before_subscribe)
|
|
15
|
+
# * [after_subscribe](rdoc-ref:ClassMethods#after_subscribe) (aliased as
|
|
16
|
+
# [on_subscribe](rdoc-ref:ClassMethods#on_subscribe))
|
|
17
|
+
# * [before_unsubscribe](rdoc-ref:ClassMethods#before_unsubscribe)
|
|
18
|
+
# * [after_unsubscribe](rdoc-ref:ClassMethods#after_unsubscribe) (aliased as
|
|
19
|
+
# [on_unsubscribe](rdoc-ref:ClassMethods#on_unsubscribe))
|
|
11
20
|
#
|
|
12
|
-
# * {before_subscribe}[rdoc-ref:ClassMethods#before_subscribe]
|
|
13
|
-
# * {after_subscribe}[rdoc-ref:ClassMethods#after_subscribe] (aliased as
|
|
14
|
-
# {on_subscribe}[rdoc-ref:ClassMethods#on_subscribe])
|
|
15
|
-
# * {before_unsubscribe}[rdoc-ref:ClassMethods#before_unsubscribe]
|
|
16
|
-
# * {after_unsubscribe}[rdoc-ref:ClassMethods#after_unsubscribe] (aliased as
|
|
17
|
-
# {on_unsubscribe}[rdoc-ref:ClassMethods#on_unsubscribe])
|
|
18
21
|
#
|
|
19
|
-
#
|
|
22
|
+
# #### Example
|
|
20
23
|
#
|
|
21
|
-
#
|
|
22
|
-
#
|
|
23
|
-
#
|
|
24
|
+
# class ChatChannel < ApplicationCable::Channel
|
|
25
|
+
# after_subscribe :send_welcome_message, unless: :subscription_rejected?
|
|
26
|
+
# after_subscribe :track_subscription
|
|
24
27
|
#
|
|
25
|
-
#
|
|
26
|
-
#
|
|
27
|
-
#
|
|
28
|
-
#
|
|
28
|
+
# private
|
|
29
|
+
# def send_welcome_message
|
|
30
|
+
# broadcast_to(...)
|
|
31
|
+
# end
|
|
29
32
|
#
|
|
30
|
-
#
|
|
31
|
-
#
|
|
32
|
-
#
|
|
33
|
-
#
|
|
33
|
+
# def track_subscription
|
|
34
|
+
# # ...
|
|
35
|
+
# end
|
|
36
|
+
# end
|
|
34
37
|
#
|
|
35
38
|
module Callbacks
|
|
36
39
|
extend ActiveSupport::Concern
|
|
@@ -46,14 +49,13 @@ module ActionCable
|
|
|
46
49
|
set_callback(:subscribe, :before, *methods, &block)
|
|
47
50
|
end
|
|
48
51
|
|
|
49
|
-
# This callback will be triggered after the Base#subscribed method is
|
|
50
|
-
#
|
|
51
|
-
# method.
|
|
52
|
+
# This callback will be triggered after the Base#subscribed method is called,
|
|
53
|
+
# even if the subscription was rejected with the Base#reject method.
|
|
52
54
|
#
|
|
53
55
|
# To trigger the callback only on successful subscriptions, use the
|
|
54
56
|
# Base#subscription_rejected? method:
|
|
55
57
|
#
|
|
56
|
-
#
|
|
58
|
+
# after_subscribe :my_method, unless: :subscription_rejected?
|
|
57
59
|
#
|
|
58
60
|
def after_subscribe(*methods, &block)
|
|
59
61
|
set_callback(:subscribe, :after, *methods, &block)
|
|
@@ -1,26 +1,27 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
# :markup: markdown
|
|
4
|
+
|
|
3
5
|
module ActionCable
|
|
4
6
|
module Channel
|
|
5
7
|
module Naming
|
|
6
8
|
extend ActiveSupport::Concern
|
|
7
9
|
|
|
8
10
|
module ClassMethods
|
|
9
|
-
# Returns the name of the channel, underscored, without the
|
|
10
|
-
#
|
|
11
|
+
# Returns the name of the channel, underscored, without the `Channel` ending. If
|
|
12
|
+
# the channel is in a namespace, then the namespaces are represented by single
|
|
11
13
|
# colon separators in the channel name.
|
|
12
14
|
#
|
|
13
|
-
#
|
|
14
|
-
#
|
|
15
|
-
#
|
|
15
|
+
# ChatChannel.channel_name # => 'chat'
|
|
16
|
+
# Chats::AppearancesChannel.channel_name # => 'chats:appearances'
|
|
17
|
+
# FooChats::BarAppearancesChannel.channel_name # => 'foo_chats:bar_appearances'
|
|
16
18
|
def channel_name
|
|
17
19
|
@channel_name ||= name.delete_suffix("Channel").gsub("::", ":").underscore
|
|
18
20
|
end
|
|
19
21
|
end
|
|
20
22
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
delegate :channel_name, to: :class
|
|
23
|
+
def channel_name
|
|
24
|
+
self.class.channel_name
|
|
24
25
|
end
|
|
25
26
|
end
|
|
26
27
|
end
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
# :markup: markdown
|
|
4
|
+
|
|
3
5
|
module ActionCable
|
|
4
6
|
module Channel
|
|
5
7
|
module PeriodicTimers
|
|
@@ -13,14 +15,12 @@ module ActionCable
|
|
|
13
15
|
end
|
|
14
16
|
|
|
15
17
|
module ClassMethods
|
|
16
|
-
# Periodically performs a task on the channel, like updating an online
|
|
17
|
-
#
|
|
18
|
-
#
|
|
19
|
-
# progress updates.
|
|
18
|
+
# Periodically performs a task on the channel, like updating an online user
|
|
19
|
+
# counter, polling a backend for new status messages, sending regular
|
|
20
|
+
# "heartbeat" messages, or doing some internal work and giving progress updates.
|
|
20
21
|
#
|
|
21
|
-
# Pass a method name or lambda argument or provide a block to call.
|
|
22
|
-
#
|
|
23
|
-
# keyword argument.
|
|
22
|
+
# Pass a method name or lambda argument or provide a block to call. Specify the
|
|
23
|
+
# calling period in seconds using the `every:` keyword argument.
|
|
24
24
|
#
|
|
25
25
|
# periodically :transmit_progress, every: 5.seconds
|
|
26
26
|
#
|
|
@@ -1,67 +1,77 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
# :markup: markdown
|
|
4
|
+
|
|
3
5
|
module ActionCable
|
|
4
6
|
module Channel
|
|
5
|
-
#
|
|
6
|
-
#
|
|
7
|
-
# Streams allow channels to route broadcastings to the subscriber. A
|
|
8
|
-
#
|
|
9
|
-
#
|
|
10
|
-
#
|
|
11
|
-
#
|
|
12
|
-
#
|
|
13
|
-
#
|
|
14
|
-
#
|
|
15
|
-
#
|
|
16
|
-
#
|
|
17
|
-
#
|
|
18
|
-
#
|
|
7
|
+
# # Action Cable Channel Streams
|
|
8
|
+
#
|
|
9
|
+
# Streams allow channels to route broadcastings to the subscriber. A
|
|
10
|
+
# broadcasting is, as discussed elsewhere, a pubsub queue where any data placed
|
|
11
|
+
# into it is automatically sent to the clients that are connected at that time.
|
|
12
|
+
# It's purely an online queue, though. If you're not streaming a broadcasting at
|
|
13
|
+
# the very moment it sends out an update, you will not get that update, even if
|
|
14
|
+
# you connect after it has been sent.
|
|
15
|
+
#
|
|
16
|
+
# Most commonly, the streamed broadcast is sent straight to the subscriber on
|
|
17
|
+
# the client-side. The channel just acts as a connector between the two parties
|
|
18
|
+
# (the broadcaster and the channel subscriber). Here's an example of a channel
|
|
19
|
+
# that allows subscribers to get all new comments on a given page:
|
|
20
|
+
#
|
|
21
|
+
# class CommentsChannel < ApplicationCable::Channel
|
|
22
|
+
# def follow(data)
|
|
23
|
+
# stream_from "comments_for_#{data['recording_id']}"
|
|
24
|
+
# end
|
|
19
25
|
#
|
|
20
|
-
#
|
|
21
|
-
#
|
|
26
|
+
# def unfollow
|
|
27
|
+
# stop_all_streams
|
|
28
|
+
# end
|
|
22
29
|
# end
|
|
23
|
-
# end
|
|
24
30
|
#
|
|
25
|
-
# Based on the above example, the subscribers of this channel will get whatever
|
|
26
|
-
# let's say,
|
|
31
|
+
# Based on the above example, the subscribers of this channel will get whatever
|
|
32
|
+
# data is put into the, let's say, `comments_for_45` broadcasting as soon as
|
|
33
|
+
# it's put there.
|
|
27
34
|
#
|
|
28
35
|
# An example broadcasting for this channel looks like so:
|
|
29
36
|
#
|
|
30
|
-
#
|
|
37
|
+
# ActionCable.server.broadcast "comments_for_45", { author: 'DHH', content: 'Rails is just swell' }
|
|
31
38
|
#
|
|
32
|
-
# If you have a stream that is related to a model, then the broadcasting used
|
|
33
|
-
#
|
|
39
|
+
# If you have a stream that is related to a model, then the broadcasting used
|
|
40
|
+
# can be generated from the model and channel. The following example would
|
|
41
|
+
# subscribe to a broadcasting like `comments:Z2lkOi8vVGVzdEFwcC9Qb3N0LzE`.
|
|
34
42
|
#
|
|
35
|
-
#
|
|
36
|
-
#
|
|
37
|
-
#
|
|
38
|
-
#
|
|
43
|
+
# class CommentsChannel < ApplicationCable::Channel
|
|
44
|
+
# def subscribed
|
|
45
|
+
# post = Post.find(params[:id])
|
|
46
|
+
# stream_for post
|
|
47
|
+
# end
|
|
39
48
|
# end
|
|
40
|
-
# end
|
|
41
49
|
#
|
|
42
50
|
# You can then broadcast to this channel using:
|
|
43
51
|
#
|
|
44
|
-
#
|
|
52
|
+
# CommentsChannel.broadcast_to(@post, @comment)
|
|
45
53
|
#
|
|
46
|
-
# If you don't just want to parlay the broadcast unfiltered to the subscriber,
|
|
47
|
-
#
|
|
54
|
+
# If you don't just want to parlay the broadcast unfiltered to the subscriber,
|
|
55
|
+
# you can also supply a callback that lets you alter what is sent out. The below
|
|
56
|
+
# example shows how you can use this to provide performance introspection in the
|
|
57
|
+
# process:
|
|
48
58
|
#
|
|
49
|
-
#
|
|
50
|
-
#
|
|
51
|
-
#
|
|
59
|
+
# class ChatChannel < ApplicationCable::Channel
|
|
60
|
+
# def subscribed
|
|
61
|
+
# @room = Chat::Room[params[:room_number]]
|
|
52
62
|
#
|
|
53
|
-
#
|
|
54
|
-
#
|
|
55
|
-
#
|
|
63
|
+
# stream_for @room, coder: ActiveSupport::JSON do |message|
|
|
64
|
+
# if message['originated_at'].present?
|
|
65
|
+
# elapsed_time = (Time.now.to_f - message['originated_at']).round(2)
|
|
56
66
|
#
|
|
57
|
-
#
|
|
58
|
-
#
|
|
59
|
-
#
|
|
67
|
+
# ActiveSupport::Notifications.instrument :performance, measurement: 'Chat.message_delay', value: elapsed_time, action: :timing
|
|
68
|
+
# logger.info "Message took #{elapsed_time}s to arrive"
|
|
69
|
+
# end
|
|
60
70
|
#
|
|
61
|
-
#
|
|
71
|
+
# transmit message
|
|
72
|
+
# end
|
|
62
73
|
# end
|
|
63
74
|
# end
|
|
64
|
-
# end
|
|
65
75
|
#
|
|
66
76
|
# You can stop streaming from all broadcasts by calling #stop_all_streams.
|
|
67
77
|
module Streams
|
|
@@ -71,18 +81,22 @@ module ActionCable
|
|
|
71
81
|
on_unsubscribe :stop_all_streams
|
|
72
82
|
end
|
|
73
83
|
|
|
74
|
-
# Start streaming from the named
|
|
75
|
-
#
|
|
76
|
-
#
|
|
77
|
-
#
|
|
84
|
+
# Start streaming from the named `broadcasting` pubsub queue. Optionally, you
|
|
85
|
+
# can pass a `callback` that'll be used instead of the default of just
|
|
86
|
+
# transmitting the updates straight to the subscriber. Pass `coder:
|
|
87
|
+
# ActiveSupport::JSON` to decode messages as JSON before passing to the
|
|
88
|
+
# callback. Defaults to `coder: nil` which does no decoding, passes raw
|
|
89
|
+
# messages.
|
|
78
90
|
def stream_from(broadcasting, callback = nil, coder: nil, &block)
|
|
91
|
+
return if unsubscribed?
|
|
92
|
+
|
|
79
93
|
broadcasting = String(broadcasting)
|
|
80
94
|
|
|
81
95
|
# Don't send the confirmation until pubsub#subscribe is successful
|
|
82
96
|
defer_subscription_confirmation!
|
|
83
97
|
|
|
84
|
-
# Build a stream handler by wrapping the user-provided callback with
|
|
85
|
-
#
|
|
98
|
+
# Build a stream handler by wrapping the user-provided callback with a decoder
|
|
99
|
+
# or defaulting to a JSON-decoding retransmitter.
|
|
86
100
|
handler = worker_pool_stream_handler(broadcasting, callback || block, coder: coder)
|
|
87
101
|
streams[broadcasting] = handler
|
|
88
102
|
|
|
@@ -94,17 +108,18 @@ module ActionCable
|
|
|
94
108
|
end
|
|
95
109
|
end
|
|
96
110
|
|
|
97
|
-
# Start streaming the pubsub queue for the
|
|
98
|
-
#
|
|
99
|
-
# to the subscriber.
|
|
111
|
+
# Start streaming the pubsub queue for the `model` in this channel. Optionally,
|
|
112
|
+
# you can pass a `callback` that'll be used instead of the default of just
|
|
113
|
+
# transmitting the updates straight to the subscriber.
|
|
100
114
|
#
|
|
101
|
-
# Pass
|
|
102
|
-
# Defaults to
|
|
115
|
+
# Pass `coder: ActiveSupport::JSON` to decode messages as JSON before passing to
|
|
116
|
+
# the callback. Defaults to `coder: nil` which does no decoding, passes raw
|
|
117
|
+
# messages.
|
|
103
118
|
def stream_for(model, callback = nil, coder: nil, &block)
|
|
104
119
|
stream_from(broadcasting_for(model), callback || block, coder: coder)
|
|
105
120
|
end
|
|
106
121
|
|
|
107
|
-
# Unsubscribes streams from the named
|
|
122
|
+
# Unsubscribes streams from the named `broadcasting`.
|
|
108
123
|
def stop_stream_from(broadcasting)
|
|
109
124
|
callback = streams.delete(broadcasting)
|
|
110
125
|
if callback
|
|
@@ -113,7 +128,7 @@ module ActionCable
|
|
|
113
128
|
end
|
|
114
129
|
end
|
|
115
130
|
|
|
116
|
-
# Unsubscribes streams for the
|
|
131
|
+
# Unsubscribes streams for the `model`.
|
|
117
132
|
def stop_stream_for(model)
|
|
118
133
|
stop_stream_from(broadcasting_for(model))
|
|
119
134
|
end
|
|
@@ -126,7 +141,7 @@ module ActionCable
|
|
|
126
141
|
end.clear
|
|
127
142
|
end
|
|
128
143
|
|
|
129
|
-
# Calls stream_for with the given
|
|
144
|
+
# Calls stream_for with the given `model` if it's present to start streaming,
|
|
130
145
|
# otherwise rejects the subscription.
|
|
131
146
|
def stream_or_reject_for(model)
|
|
132
147
|
if model
|
|
@@ -143,8 +158,8 @@ module ActionCable
|
|
|
143
158
|
@_streams ||= {}
|
|
144
159
|
end
|
|
145
160
|
|
|
146
|
-
# Always wrap the outermost handler to invoke the user handler on the
|
|
147
|
-
#
|
|
161
|
+
# Always wrap the outermost handler to invoke the user handler on the worker
|
|
162
|
+
# pool rather than blocking the event loop.
|
|
148
163
|
def worker_pool_stream_handler(broadcasting, user_handler, coder: nil)
|
|
149
164
|
handler = stream_handler(broadcasting, user_handler, coder: coder)
|
|
150
165
|
|
|
@@ -153,8 +168,8 @@ module ActionCable
|
|
|
153
168
|
end
|
|
154
169
|
end
|
|
155
170
|
|
|
156
|
-
# May be overridden to add instrumentation, logging, specialized error
|
|
157
|
-
#
|
|
171
|
+
# May be overridden to add instrumentation, logging, specialized error handling,
|
|
172
|
+
# or other forms of handler decoration.
|
|
158
173
|
#
|
|
159
174
|
# TODO: Tests demonstrating this.
|
|
160
175
|
def stream_handler(broadcasting, user_handler, coder: nil)
|
|
@@ -165,14 +180,14 @@ module ActionCable
|
|
|
165
180
|
end
|
|
166
181
|
end
|
|
167
182
|
|
|
168
|
-
# May be overridden to change the default stream handling behavior
|
|
169
|
-
#
|
|
183
|
+
# May be overridden to change the default stream handling behavior which decodes
|
|
184
|
+
# JSON and transmits to the client.
|
|
170
185
|
#
|
|
171
186
|
# TODO: Tests demonstrating this.
|
|
172
187
|
#
|
|
173
|
-
# TODO: Room for optimization. Update transmit API to be coder-aware
|
|
174
|
-
#
|
|
175
|
-
#
|
|
188
|
+
# TODO: Room for optimization. Update transmit API to be coder-aware so we can
|
|
189
|
+
# no-op when pubsub and connection are both JSON-encoded. Then we can skip
|
|
190
|
+
# decode+encode if we're just proxying messages.
|
|
176
191
|
def default_stream_handler(broadcasting, coder:)
|
|
177
192
|
coder ||= ActiveSupport::JSON
|
|
178
193
|
stream_transmitter stream_decoder(coder: coder), broadcasting: broadcasting
|