actioncable 7.1.3.4 → 7.2.1

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.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +26 -129
  3. data/app/assets/javascripts/action_cable.js +3 -3
  4. data/app/assets/javascripts/actioncable.esm.js +3 -3
  5. data/app/assets/javascripts/actioncable.js +3 -3
  6. data/lib/action_cable/channel/base.rb +98 -86
  7. data/lib/action_cable/channel/broadcasting.rb +25 -18
  8. data/lib/action_cable/channel/callbacks.rb +27 -25
  9. data/lib/action_cable/channel/naming.rb +9 -8
  10. data/lib/action_cable/channel/periodic_timers.rb +7 -7
  11. data/lib/action_cable/channel/streams.rb +77 -64
  12. data/lib/action_cable/channel/test_case.rb +112 -86
  13. data/lib/action_cable/connection/authorization.rb +4 -1
  14. data/lib/action_cable/connection/base.rb +53 -38
  15. data/lib/action_cable/connection/callbacks.rb +20 -18
  16. data/lib/action_cable/connection/client_socket.rb +3 -1
  17. data/lib/action_cable/connection/identification.rb +9 -5
  18. data/lib/action_cable/connection/internal_channel.rb +5 -2
  19. data/lib/action_cable/connection/message_buffer.rb +4 -1
  20. data/lib/action_cable/connection/stream.rb +2 -0
  21. data/lib/action_cable/connection/stream_event_loop.rb +4 -3
  22. data/lib/action_cable/connection/subscriptions.rb +6 -3
  23. data/lib/action_cable/connection/tagged_logger_proxy.rb +7 -4
  24. data/lib/action_cable/connection/test_case.rb +66 -56
  25. data/lib/action_cable/connection/web_socket.rb +10 -8
  26. data/lib/action_cable/deprecator.rb +2 -0
  27. data/lib/action_cable/engine.rb +5 -3
  28. data/lib/action_cable/gem_version.rb +6 -4
  29. data/lib/action_cable/helpers/action_cable_helper.rb +21 -19
  30. data/lib/action_cable/remote_connections.rb +19 -16
  31. data/lib/action_cable/server/base.rb +27 -15
  32. data/lib/action_cable/server/broadcasting.rb +23 -17
  33. data/lib/action_cable/server/configuration.rb +17 -14
  34. data/lib/action_cable/server/connections.rb +11 -5
  35. data/lib/action_cable/server/worker/active_record_connection_management.rb +2 -0
  36. data/lib/action_cable/server/worker.rb +4 -2
  37. data/lib/action_cable/subscription_adapter/async.rb +2 -0
  38. data/lib/action_cable/subscription_adapter/base.rb +2 -0
  39. data/lib/action_cable/subscription_adapter/channel_prefix.rb +2 -0
  40. data/lib/action_cable/subscription_adapter/inline.rb +2 -0
  41. data/lib/action_cable/subscription_adapter/postgresql.rb +4 -2
  42. data/lib/action_cable/subscription_adapter/redis.rb +5 -2
  43. data/lib/action_cable/subscription_adapter/subscriber_map.rb +2 -0
  44. data/lib/action_cable/subscription_adapter/test.rb +8 -5
  45. data/lib/action_cable/test_case.rb +2 -0
  46. data/lib/action_cable/test_helper.rb +51 -52
  47. data/lib/action_cable/version.rb +3 -1
  48. data/lib/action_cable.rb +13 -7
  49. data/lib/rails/generators/channel/channel_generator.rb +4 -2
  50. data/lib/rails/generators/test_unit/channel_generator.rb +2 -0
  51. metadata +13 -13
  52. /data/lib/rails/generators/channel/templates/application_cable/{channel.rb → channel.rb.tt} +0 -0
  53. /data/lib/rails/generators/channel/templates/application_cable/{connection.rb → connection.rb.tt} +0 -0
@@ -1,12 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  module ActionCable
4
6
  module Connection
5
- # = Action Cable \Connection \TaggedLoggerProxy
7
+ # # Action Cable Connection TaggedLoggerProxy
6
8
  #
7
- # Allows the use of per-connection tags against the server logger. This wouldn't work using the traditional
8
- # ActiveSupport::TaggedLogging enhanced Rails.logger, as that logger will reset the tags between requests.
9
- # The connection is long-lived, so it needs its own set of tags for its independent duration.
9
+ # Allows the use of per-connection tags against the server logger. This wouldn't
10
+ # work using the traditional ActiveSupport::TaggedLogging enhanced Rails.logger,
11
+ # as that logger will reset the tags between requests. The connection is
12
+ # long-lived, so it needs its own set of tags for its independent duration.
10
13
  class TaggedLoggerProxy
11
14
  attr_reader :tags
12
15
 
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  require "active_support"
4
6
  require "active_support/test_case"
5
7
  require "active_support/core_ext/hash/indifferent_access"
@@ -18,25 +20,33 @@ module ActionCable
18
20
  end
19
21
 
20
22
  module Assertions
21
- # Asserts that the connection is rejected (via +reject_unauthorized_connection+).
23
+ # Asserts that the connection is rejected (via
24
+ # `reject_unauthorized_connection`).
22
25
  #
23
- # # Asserts that connection without user_id fails
24
- # assert_reject_connection { connect params: { user_id: '' } }
26
+ # # Asserts that connection without user_id fails
27
+ # assert_reject_connection { connect params: { user_id: '' } }
25
28
  def assert_reject_connection(&block)
26
29
  assert_raises(Authorization::UnauthorizedError, "Expected to reject connection but no rejection was made", &block)
27
30
  end
28
31
  end
29
32
 
30
- # We don't want to use the whole "encryption stack" for connection
31
- # unit-tests, but we want to make sure that users test against the correct types
32
- # of cookies (i.e. signed or encrypted or plain)
33
- class TestCookieJar < ActiveSupport::HashWithIndifferentAccess
33
+ class TestCookies < ActiveSupport::HashWithIndifferentAccess # :nodoc:
34
+ def []=(name, options)
35
+ value = options.is_a?(Hash) ? options.symbolize_keys[:value] : options
36
+ super(name, value)
37
+ end
38
+ end
39
+
40
+ # We don't want to use the whole "encryption stack" for connection unit-tests,
41
+ # but we want to make sure that users test against the correct types of cookies
42
+ # (i.e. signed or encrypted or plain)
43
+ class TestCookieJar < TestCookies
34
44
  def signed
35
- self[:signed] ||= {}.with_indifferent_access
45
+ @signed ||= TestCookies.new
36
46
  end
37
47
 
38
48
  def encrypted
39
- self[:encrypted] ||= {}.with_indifferent_access
49
+ @encrypted ||= TestCookies.new
40
50
  end
41
51
  end
42
52
 
@@ -56,77 +66,77 @@ module ActionCable
56
66
  end
57
67
  end
58
68
 
59
- # = Action Cable \Connection \TestCase
69
+ # # Action Cable Connection TestCase
60
70
  #
61
71
  # Unit test Action Cable connections.
62
72
  #
63
- # Useful to check whether a connection's +identified_by+ gets assigned properly
73
+ # Useful to check whether a connection's `identified_by` gets assigned properly
64
74
  # and that any improper connection requests are rejected.
65
75
  #
66
- # == Basic example
76
+ # ## Basic example
67
77
  #
68
78
  # Unit tests are written as follows:
69
79
  #
70
- # 1. Simulate a connection attempt by calling +connect+.
71
- # 2. Assert state, e.g. identifiers, has been assigned.
80
+ # 1. Simulate a connection attempt by calling `connect`.
81
+ # 2. Assert state, e.g. identifiers, has been assigned.
72
82
  #
73
83
  #
74
- # class ApplicationCable::ConnectionTest < ActionCable::Connection::TestCase
75
- # def test_connects_with_proper_cookie
76
- # # Simulate the connection request with a cookie.
77
- # cookies["user_id"] = users(:john).id
84
+ # class ApplicationCable::ConnectionTest < ActionCable::Connection::TestCase
85
+ # def test_connects_with_proper_cookie
86
+ # # Simulate the connection request with a cookie.
87
+ # cookies["user_id"] = users(:john).id
78
88
  #
79
- # connect
89
+ # connect
80
90
  #
81
- # # Assert the connection identifier matches the fixture.
82
- # assert_equal users(:john).id, connection.user.id
83
- # end
91
+ # # Assert the connection identifier matches the fixture.
92
+ # assert_equal users(:john).id, connection.user.id
93
+ # end
84
94
  #
85
- # def test_rejects_connection_without_proper_cookie
86
- # assert_reject_connection { connect }
95
+ # def test_rejects_connection_without_proper_cookie
96
+ # assert_reject_connection { connect }
97
+ # end
87
98
  # end
88
- # end
89
99
  #
90
- # +connect+ accepts additional information about the HTTP request with the
91
- # +params+, +headers+, +session+, and Rack +env+ options.
100
+ # `connect` accepts additional information about the HTTP request with the
101
+ # `params`, `headers`, `session`, and Rack `env` options.
92
102
  #
93
- # def test_connect_with_headers_and_query_string
94
- # connect params: { user_id: 1 }, headers: { "X-API-TOKEN" => "secret-my" }
103
+ # def test_connect_with_headers_and_query_string
104
+ # connect params: { user_id: 1 }, headers: { "X-API-TOKEN" => "secret-my" }
95
105
  #
96
- # assert_equal "1", connection.user.id
97
- # assert_equal "secret-my", connection.token
98
- # end
106
+ # assert_equal "1", connection.user.id
107
+ # assert_equal "secret-my", connection.token
108
+ # end
99
109
  #
100
- # def test_connect_with_params
101
- # connect params: { user_id: 1 }
110
+ # def test_connect_with_params
111
+ # connect params: { user_id: 1 }
102
112
  #
103
- # assert_equal "1", connection.user.id
104
- # end
113
+ # assert_equal "1", connection.user.id
114
+ # end
105
115
  #
106
116
  # You can also set up the correct cookies before the connection request:
107
117
  #
108
- # def test_connect_with_cookies
109
- # # Plain cookies:
110
- # cookies["user_id"] = 1
118
+ # def test_connect_with_cookies
119
+ # # Plain cookies:
120
+ # cookies["user_id"] = 1
111
121
  #
112
- # # Or signed/encrypted:
113
- # # cookies.signed["user_id"] = 1
114
- # # cookies.encrypted["user_id"] = 1
122
+ # # Or signed/encrypted:
123
+ # # cookies.signed["user_id"] = 1
124
+ # # cookies.encrypted["user_id"] = 1
115
125
  #
116
- # connect
126
+ # connect
117
127
  #
118
- # assert_equal "1", connection.user_id
119
- # end
128
+ # assert_equal "1", connection.user_id
129
+ # end
120
130
  #
121
- # == \Connection is automatically inferred
131
+ # ## Connection is automatically inferred
122
132
  #
123
- # ActionCable::Connection::TestCase will automatically infer the connection under test
124
- # from the test class name. If the channel cannot be inferred from the test
125
- # class name, you can explicitly set it with +tests+.
133
+ # ActionCable::Connection::TestCase will automatically infer the connection
134
+ # under test from the test class name. If the channel cannot be inferred from
135
+ # the test class name, you can explicitly set it with `tests`.
126
136
  #
127
- # class ConnectionTest < ActionCable::Connection::TestCase
128
- # tests ApplicationCable::Connection
129
- # end
137
+ # class ConnectionTest < ActionCable::Connection::TestCase
138
+ # tests ApplicationCable::Connection
139
+ # end
130
140
  #
131
141
  class TestCase < ActiveSupport::TestCase
132
142
  module Behavior
@@ -178,10 +188,10 @@ module ActionCable
178
188
  #
179
189
  # Accepts request path as the first argument and the following request options:
180
190
  #
181
- # - params – URL parameters (Hash)
182
- # - headers – request headers (Hash)
183
- # - session – session data (Hash)
184
- # - env – additional Rack env configuration (Hash)
191
+ # * params – URL parameters (Hash)
192
+ # * headers – request headers (Hash)
193
+ # * session – session data (Hash)
194
+ # * env – additional Rack env configuration (Hash)
185
195
  def connect(path = ActionCable.server.config.mount_path, **request_params)
186
196
  path ||= DEFAULT_PATH
187
197
 
@@ -1,10 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  require "websocket/driver"
4
6
 
5
7
  module ActionCable
6
8
  module Connection
7
- # = Action Cable \Connection \WebSocket
9
+ # # Action Cable Connection WebSocket
8
10
  #
9
11
  # Wrap the real socket to minimize the externally-presented API
10
12
  class WebSocket # :nodoc:
@@ -17,23 +19,23 @@ module ActionCable
17
19
  end
18
20
 
19
21
  def alive?
20
- websocket && websocket.alive?
22
+ websocket&.alive?
21
23
  end
22
24
 
23
- def transmit(data)
24
- websocket.transmit data
25
+ def transmit(...)
26
+ websocket&.transmit(...)
25
27
  end
26
28
 
27
- def close
28
- websocket.close
29
+ def close(...)
30
+ websocket&.close(...)
29
31
  end
30
32
 
31
33
  def protocol
32
- websocket.protocol
34
+ websocket&.protocol
33
35
  end
34
36
 
35
37
  def rack_response
36
- websocket.rack_response
38
+ websocket&.rack_response
37
39
  end
38
40
 
39
41
  private
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  module ActionCable
4
6
  def self.deprecator # :nodoc:
5
7
  @deprecator ||= ActiveSupport::Deprecation.new
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  require "rails"
4
6
  require "action_cable"
5
7
  require "active_support/core_ext/hash/indifferent_access"
@@ -72,9 +74,9 @@ module ActionCable
72
74
  ActiveSupport.on_load(:action_cable) do
73
75
  ActionCable::Server::Worker.set_callback :work, :around, prepend: true do |_, inner|
74
76
  app.executor.wrap(source: "application.action_cable") do
75
- # If we took a while to get the lock, we may have been halted
76
- # in the meantime. As we haven't started doing any real work
77
- # yet, we should pretend that we never made it off the queue.
77
+ # If we took a while to get the lock, we may have been halted in the meantime.
78
+ # As we haven't started doing any real work yet, we should pretend that we never
79
+ # made it off the queue.
78
80
  unless stopping?
79
81
  inner.call
80
82
  end
@@ -1,16 +1,18 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  module ActionCable
4
- # Returns the currently loaded version of Action Cable as a +Gem::Version+.
6
+ # Returns the currently loaded version of Action Cable as a `Gem::Version`.
5
7
  def self.gem_version
6
8
  Gem::Version.new VERSION::STRING
7
9
  end
8
10
 
9
11
  module VERSION
10
12
  MAJOR = 7
11
- MINOR = 1
12
- TINY = 3
13
- PRE = "4"
13
+ MINOR = 2
14
+ TINY = 1
15
+ PRE = nil
14
16
 
15
17
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
16
18
  end
@@ -1,35 +1,37 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  module ActionCable
4
6
  module Helpers
5
7
  module ActionCableHelper
6
- # Returns an "action-cable-url" meta tag with the value of the URL specified in your
7
- # configuration. Ensure this is above your JavaScript tag:
8
+ # Returns an "action-cable-url" meta tag with the value of the URL specified in
9
+ # your configuration. Ensure this is above your JavaScript tag:
8
10
  #
9
- # <head>
10
- # <%= action_cable_meta_tag %>
11
- # <%= javascript_include_tag 'application', 'data-turbo-track' => 'reload' %>
12
- # </head>
11
+ # <head>
12
+ # <%= action_cable_meta_tag %>
13
+ # <%= javascript_include_tag 'application', 'data-turbo-track' => 'reload' %>
14
+ # </head>
13
15
  #
14
- # This is then used by Action Cable to determine the URL of your WebSocket server.
15
- # Your JavaScript can then connect to the server without needing to specify the
16
- # URL directly:
16
+ # This is then used by Action Cable to determine the URL of your WebSocket
17
+ # server. Your JavaScript can then connect to the server without needing to
18
+ # specify the URL directly:
17
19
  #
18
- # import Cable from "@rails/actioncable"
19
- # window.Cable = Cable
20
- # window.App = {}
21
- # App.cable = Cable.createConsumer()
20
+ # import Cable from "@rails/actioncable"
21
+ # window.Cable = Cable
22
+ # window.App = {}
23
+ # App.cable = Cable.createConsumer()
22
24
  #
23
25
  # Make sure to specify the correct server location in each of your environment
24
26
  # config files:
25
27
  #
26
- # config.action_cable.mount_path = "/cable123"
27
- # <%= action_cable_meta_tag %> would render:
28
- # => <meta name="action-cable-url" content="/cable123" />
28
+ # config.action_cable.mount_path = "/cable123"
29
+ # <%= action_cable_meta_tag %> would render:
30
+ # => <meta name="action-cable-url" content="/cable123" />
29
31
  #
30
- # config.action_cable.url = "ws://actioncable.com"
31
- # <%= action_cable_meta_tag %> would render:
32
- # => <meta name="action-cable-url" content="ws://actioncable.com" />
32
+ # config.action_cable.url = "ws://actioncable.com"
33
+ # <%= action_cable_meta_tag %> would render:
34
+ # => <meta name="action-cable-url" content="ws://actioncable.com" />
33
35
  #
34
36
  def action_cable_meta_tag
35
37
  tag "meta", name: "action-cable-url", content: (
@@ -1,31 +1,33 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  require "active_support/core_ext/module/redefine_method"
4
6
 
5
7
  module ActionCable
6
- # = Action Cable Remote Connections
8
+ # # Action Cable Remote Connections
7
9
  #
8
10
  # If you need to disconnect a given connection, you can go through the
9
11
  # RemoteConnections. You can find the connections you're looking for by
10
12
  # searching for the identifier declared on the connection. For example:
11
13
  #
12
- # module ApplicationCable
13
- # class Connection < ActionCable::Connection::Base
14
- # identified_by :current_user
15
- # ....
14
+ # module ApplicationCable
15
+ # class Connection < ActionCable::Connection::Base
16
+ # identified_by :current_user
17
+ # ....
18
+ # end
16
19
  # end
17
- # end
18
20
  #
19
- # ActionCable.server.remote_connections.where(current_user: User.find(1)).disconnect
21
+ # ActionCable.server.remote_connections.where(current_user: User.find(1)).disconnect
20
22
  #
21
- # This will disconnect all the connections established for
22
- # <tt>User.find(1)</tt>, across all servers running on all machines, because
23
- # it uses the internal channel that all of these servers are subscribed to.
23
+ # This will disconnect all the connections established for `User.find(1)`,
24
+ # across all servers running on all machines, because it uses the internal
25
+ # channel that all of these servers are subscribed to.
24
26
  #
25
- # By default, server sends a "disconnect" message with "reconnect" flag set to true.
26
- # You can override it by specifying the +reconnect+ option:
27
+ # By default, server sends a "disconnect" message with "reconnect" flag set to
28
+ # true. You can override it by specifying the `reconnect` option:
27
29
  #
28
- # ActionCable.server.remote_connections.where(current_user: User.find(1)).disconnect(reconnect: false)
30
+ # ActionCable.server.remote_connections.where(current_user: User.find(1)).disconnect(reconnect: false)
29
31
  class RemoteConnections
30
32
  attr_reader :server
31
33
 
@@ -38,10 +40,11 @@ module ActionCable
38
40
  end
39
41
 
40
42
  private
41
- # = Action Cable Remote \Connection
43
+ # # Action Cable Remote Connection
42
44
  #
43
- # Represents a single remote connection found via <tt>ActionCable.server.remote_connections.where(*)</tt>.
44
- # Exists solely for the purpose of calling #disconnect on that connection.
45
+ # Represents a single remote connection found via
46
+ # `ActionCable.server.remote_connections.where(*)`. Exists solely for the
47
+ # purpose of calling #disconnect on that connection.
45
48
  class RemoteConnection
46
49
  class InvalidIdentifiersError < StandardError; end
47
50
 
@@ -1,15 +1,20 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  require "monitor"
4
6
 
5
7
  module ActionCable
6
8
  module Server
7
- # = Action Cable \Server \Base
9
+ # # Action Cable Server Base
8
10
  #
9
- # A singleton ActionCable::Server instance is available via ActionCable.server. It's used by the Rack process that starts the Action Cable server, but
10
- # is also used by the user to reach the RemoteConnections object, which is used for finding and disconnecting connections across all servers.
11
+ # A singleton ActionCable::Server instance is available via ActionCable.server.
12
+ # It's used by the Rack process that starts the Action Cable server, but is also
13
+ # used by the user to reach the RemoteConnections object, which is used for
14
+ # finding and disconnecting connections across all servers.
11
15
  #
12
- # Also, this is the server instance used for broadcasting. See Broadcasting for more information.
16
+ # Also, this is the server instance used for broadcasting. See Broadcasting for
17
+ # more information.
13
18
  class Base
14
19
  include ActionCable::Server::Broadcasting
15
20
  include ActionCable::Server::Connections
@@ -36,7 +41,8 @@ module ActionCable
36
41
  config.connection_class.call.new(self, env).process
37
42
  end
38
43
 
39
- # Disconnect all the connections identified by +identifiers+ on this server or any others via RemoteConnections.
44
+ # Disconnect all the connections identified by `identifiers` on this server or
45
+ # any others via RemoteConnections.
40
46
  def disconnect(identifiers)
41
47
  remote_connections.where(identifiers).disconnect
42
48
  end
@@ -66,17 +72,22 @@ module ActionCable
66
72
  @event_loop || @mutex.synchronize { @event_loop ||= ActionCable::Connection::StreamEventLoop.new }
67
73
  end
68
74
 
69
- # The worker pool is where we run connection callbacks and channel actions. We do as little as possible on the server's main thread.
70
- # The worker pool is an executor service that's backed by a pool of threads working from a task queue. The thread pool size maxes out
71
- # at 4 worker threads by default. Tune the size yourself with <tt>config.action_cable.worker_pool_size</tt>.
75
+ # The worker pool is where we run connection callbacks and channel actions. We
76
+ # do as little as possible on the server's main thread. The worker pool is an
77
+ # executor service that's backed by a pool of threads working from a task queue.
78
+ # The thread pool size maxes out at 4 worker threads by default. Tune the size
79
+ # yourself with `config.action_cable.worker_pool_size`.
72
80
  #
73
- # Using Active Record, Redis, etc within your channel actions means you'll get a separate connection from each thread in the worker pool.
74
- # Plan your deployment accordingly: 5 servers each running 5 Puma workers each running an 8-thread worker pool means at least 200 database
75
- # connections.
81
+ # Using Active Record, Redis, etc within your channel actions means you'll get a
82
+ # separate connection from each thread in the worker pool. Plan your deployment
83
+ # accordingly: 5 servers each running 5 Puma workers each running an 8-thread
84
+ # worker pool means at least 200 database connections.
76
85
  #
77
- # Also, ensure that your database connection pool size is as least as large as your worker pool size. Otherwise, workers may oversubscribe
78
- # the database connection pool and block while they wait for other workers to release their connections. Use a smaller worker pool or a larger
79
- # database connection pool instead.
86
+ # Also, ensure that your database connection pool size is as least as large as
87
+ # your worker pool size. Otherwise, workers may oversubscribe the database
88
+ # connection pool and block while they wait for other workers to release their
89
+ # connections. Use a smaller worker pool or a larger database connection pool
90
+ # instead.
80
91
  def worker_pool
81
92
  @worker_pool || @mutex.synchronize { @worker_pool ||= ActionCable::Server::Worker.new(max_size: config.worker_pool_size) }
82
93
  end
@@ -86,7 +97,8 @@ module ActionCable
86
97
  @pubsub || @mutex.synchronize { @pubsub ||= config.pubsub_adapter.new(self) }
87
98
  end
88
99
 
89
- # All of the identifiers applied to the connection class associated with this server.
100
+ # All of the identifiers applied to the connection class associated with this
101
+ # server.
90
102
  def connection_identifiers
91
103
  config.connection_class.call.identifiers
92
104
  end
@@ -1,34 +1,40 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  module ActionCable
4
6
  module Server
5
- # = Action Cable \Server \Broadcasting
7
+ # # Action Cable Server Broadcasting
6
8
  #
7
- # Broadcasting is how other parts of your application can send messages to a channel's subscribers. As explained in Channel, most of the time, these
8
- # broadcastings are streamed directly to the clients subscribed to the named broadcasting. Let's explain with a full-stack example:
9
+ # Broadcasting is how other parts of your application can send messages to a
10
+ # channel's subscribers. As explained in Channel, most of the time, these
11
+ # broadcastings are streamed directly to the clients subscribed to the named
12
+ # broadcasting. Let's explain with a full-stack example:
9
13
  #
10
- # class WebNotificationsChannel < ApplicationCable::Channel
11
- # def subscribed
12
- # stream_from "web_notifications_#{current_user.id}"
14
+ # class WebNotificationsChannel < ApplicationCable::Channel
15
+ # def subscribed
16
+ # stream_from "web_notifications_#{current_user.id}"
17
+ # end
13
18
  # end
14
- # end
15
19
  #
16
- # # Somewhere in your app this is called, perhaps from a NewCommentJob:
17
- # ActionCable.server.broadcast \
18
- # "web_notifications_1", { title: "New things!", body: "All that's fit for print" }
20
+ # # Somewhere in your app this is called, perhaps from a NewCommentJob:
21
+ # ActionCable.server.broadcast \
22
+ # "web_notifications_1", { title: "New things!", body: "All that's fit for print" }
19
23
  #
20
- # # Client-side CoffeeScript, which assumes you've already requested the right to send web notifications:
21
- # App.cable.subscriptions.create "WebNotificationsChannel",
22
- # received: (data) ->
23
- # new Notification data['title'], body: data['body']
24
+ # # Client-side CoffeeScript, which assumes you've already requested the right to send web notifications:
25
+ # App.cable.subscriptions.create "WebNotificationsChannel",
26
+ # received: (data) ->
27
+ # new Notification data['title'], body: data['body']
24
28
  module Broadcasting
25
- # Broadcast a hash directly to a named <tt>broadcasting</tt>. This will later be JSON encoded.
29
+ # Broadcast a hash directly to a named `broadcasting`. This will later be JSON
30
+ # encoded.
26
31
  def broadcast(broadcasting, message, coder: ActiveSupport::JSON)
27
32
  broadcaster_for(broadcasting, coder: coder).broadcast(message)
28
33
  end
29
34
 
30
- # Returns a broadcaster for a named <tt>broadcasting</tt> that can be reused. Useful when you have an object that
31
- # may need multiple spots to transmit to a specific broadcasting over and over.
35
+ # Returns a broadcaster for a named `broadcasting` that can be reused. Useful
36
+ # when you have an object that may need multiple spots to transmit to a specific
37
+ # broadcasting over and over.
32
38
  def broadcaster_for(broadcasting, coder: ActiveSupport::JSON)
33
39
  Broadcaster.new(self, String(broadcasting), coder: coder)
34
40
  end
@@ -1,13 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  require "rack"
4
6
 
5
7
  module ActionCable
6
8
  module Server
7
- # = Action Cable \Server \Configuration
9
+ # # Action Cable Server Configuration
8
10
  #
9
- # An instance of this configuration object is available via ActionCable.server.config, which allows you to tweak Action Cable configuration
10
- # in a \Rails config initializer.
11
+ # An instance of this configuration object is available via
12
+ # ActionCable.server.config, which allows you to tweak Action Cable
13
+ # configuration in a Rails config initializer.
11
14
  class Configuration
12
15
  attr_accessor :logger, :log_tags
13
16
  attr_accessor :connection_class, :worker_pool_size
@@ -31,28 +34,28 @@ module ActionCable
31
34
  }
32
35
  end
33
36
 
34
- # Returns constant of subscription adapter specified in config/cable.yml.
35
- # If the adapter cannot be found, this will default to the Redis adapter.
36
- # Also makes sure proper dependencies are required.
37
+ # Returns constant of subscription adapter specified in config/cable.yml. If the
38
+ # adapter cannot be found, this will default to the Redis adapter. Also makes
39
+ # sure proper dependencies are required.
37
40
  def pubsub_adapter
38
41
  adapter = (cable.fetch("adapter") { "redis" })
39
42
 
40
43
  # Require the adapter itself and give useful feedback about
41
- # 1. Missing adapter gems and
42
- # 2. Adapter gems' missing dependencies.
44
+ # 1. Missing adapter gems and
45
+ # 2. Adapter gems' missing dependencies.
43
46
  path_to_adapter = "action_cable/subscription_adapter/#{adapter}"
44
47
  begin
45
48
  require path_to_adapter
46
49
  rescue LoadError => e
47
- # We couldn't require the adapter itself. Raise an exception that
48
- # points out config typos and missing gems.
50
+ # We couldn't require the adapter itself. Raise an exception that points out
51
+ # config typos and missing gems.
49
52
  if e.path == path_to_adapter
50
- # We can assume that a non-builtin adapter was specified, so it's
51
- # either misspelled or missing from Gemfile.
53
+ # We can assume that a non-builtin adapter was specified, so it's either
54
+ # misspelled or missing from Gemfile.
52
55
  raise e.class, "Could not load the '#{adapter}' Action Cable pubsub adapter. Ensure that the adapter is spelled correctly in config/cable.yml and that you've added the necessary adapter gem to your Gemfile.", e.backtrace
53
56
 
54
- # Bubbled up from the adapter require. Prefix the exception message
55
- # with some guidance about how to address it and reraise.
57
+ # Bubbled up from the adapter require. Prefix the exception message with some
58
+ # guidance about how to address it and reraise.
56
59
  else
57
60
  raise e.class, "Error loading the '#{adapter}' Action Cable pubsub adapter. Missing a gem it depends on? #{e.message}", e.backtrace
58
61
  end