actioncable 7.1.5.1 → 7.2.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 +30 -138
  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 +5 -3
  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 -48
  47. data/lib/action_cable/version.rb +3 -1
  48. data/lib/action_cable.rb +12 -6
  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 +11 -11
  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,11 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  module ActionCable
4
6
  module Server
5
- # = Action Cable \Server \Connections
7
+ # # Action Cable Server Connections
6
8
  #
7
- # Collection class for all the connections that have been established on this specific server. Remember, usually you'll run many Action Cable servers, so
8
- # you can't use this collection as a full list of all of the connections established against your application. Instead, use RemoteConnections for that.
9
+ # Collection class for all the connections that have been established on this
10
+ # specific server. Remember, usually you'll run many Action Cable servers, so
11
+ # you can't use this collection as a full list of all of the connections
12
+ # established against your application. Instead, use RemoteConnections for that.
9
13
  module Connections # :nodoc:
10
14
  BEAT_INTERVAL = 3
11
15
 
@@ -21,8 +25,10 @@ module ActionCable
21
25
  connections.delete connection
22
26
  end
23
27
 
24
- # WebSocket connection implementations differ on when they'll mark a connection as stale. We basically never want a connection to go stale, as you
25
- # then can't rely on being able to communicate with the connection. To solve this, a 3 second heartbeat runs on all connections. If the beat fails, we automatically
28
+ # WebSocket connection implementations differ on when they'll mark a connection
29
+ # as stale. We basically never want a connection to go stale, as you then can't
30
+ # rely on being able to communicate with the connection. To solve this, a 3
31
+ # second heartbeat runs on all connections. If the beat fails, we automatically
26
32
  # disconnect.
27
33
  def setup_heartbeat_timer
28
34
  @heartbeat_timer ||= event_loop.timer(BEAT_INTERVAL) do
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  module ActionCable
4
6
  module Server
5
7
  class Worker
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  require "active_support/callbacks"
4
6
  require "active_support/core_ext/module/attribute_accessors_per_thread"
5
7
  require "concurrent"
@@ -25,8 +27,8 @@ module ActionCable
25
27
  )
26
28
  end
27
29
 
28
- # Stop processing work: any work that has not already started
29
- # running will be discarded from the queue
30
+ # Stop processing work: any work that has not already started running will be
31
+ # discarded from the queue
30
32
  def halt
31
33
  @executor.shutdown
32
34
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  module ActionCable
4
6
  module SubscriptionAdapter
5
7
  class Async < Inline # :nodoc:
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  module ActionCable
4
6
  module SubscriptionAdapter
5
7
  class Base
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  module ActionCable
4
6
  module SubscriptionAdapter
5
7
  module ChannelPrefix # :nodoc:
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  module ActionCable
4
6
  module SubscriptionAdapter
5
7
  class Inline < Base # :nodoc:
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  gem "pg", "~> 1.1"
4
6
  require "pg"
5
7
  require "openssl"
@@ -34,8 +36,8 @@ module ActionCable
34
36
 
35
37
  def with_subscriptions_connection(&block) # :nodoc:
36
38
  ar_conn = ActiveRecord::Base.connection_pool.checkout.tap do |conn|
37
- # Action Cable is taking ownership over this database connection, and
38
- # will perform the necessary cleanup tasks
39
+ # Action Cable is taking ownership over this database connection, and will
40
+ # perform the necessary cleanup tasks
39
41
  ActiveRecord::Base.connection_pool.remove(conn)
40
42
  end
41
43
  pg_conn = ar_conn.raw_connection
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  gem "redis", ">= 4", "< 6"
4
6
  require "redis"
5
7
 
@@ -10,8 +12,9 @@ module ActionCable
10
12
  class Redis < Base # :nodoc:
11
13
  prepend ChannelPrefix
12
14
 
13
- # Overwrite this factory method for Redis connections if you want to use a different Redis library than the redis gem.
14
- # This is needed, for example, when using Makara proxies for distributed Redis.
15
+ # Overwrite this factory method for Redis connections if you want to use a
16
+ # different Redis library than the redis gem. This is needed, for example, when
17
+ # using Makara proxies for distributed Redis.
15
18
  cattr_accessor :redis_connector, default: ->(config) do
16
19
  ::Redis.new(config.except(:adapter, :channel_prefix))
17
20
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  module ActionCable
4
6
  module SubscriptionAdapter
5
7
  class SubscriberMap
@@ -1,16 +1,19 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  module ActionCable
4
6
  module SubscriptionAdapter
5
- # == \Test adapter for Action Cable
7
+ # ## Test adapter for Action Cable
6
8
  #
7
9
  # The test adapter should be used only in testing. Along with
8
- # ActionCable::TestHelper it makes a great tool to test your \Rails application.
10
+ # ActionCable::TestHelper it makes a great tool to test your Rails application.
9
11
  #
10
- # To use the test adapter set +adapter+ value to +test+ in your +config/cable.yml+ file.
12
+ # To use the test adapter set `adapter` value to `test` in your
13
+ # `config/cable.yml` file.
11
14
  #
12
- # NOTE: +Test+ adapter extends the +ActionCable::SubscriptionAdapter::Async+ adapter,
13
- # so it could be used in system tests too.
15
+ # NOTE: `Test` adapter extends the `ActionCable::SubscriptionAdapter::Async`
16
+ # adapter, so it could be used in system tests too.
14
17
  class Test < Async
15
18
  def broadcast(channel, payload)
16
19
  broadcasts(channel) << payload
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  require "active_support/test_case"
4
6
 
5
7
  module ActionCable
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  module ActionCable
4
6
  # Provides helper methods for testing Action Cable broadcasting
5
7
  module TestHelper
@@ -18,29 +20,30 @@ module ActionCable
18
20
  ActionCable.server.instance_variable_set(:@pubsub, @old_pubsub_adapter)
19
21
  end
20
22
 
21
- # Asserts that the number of broadcasted messages to the stream matches the given number.
22
- #
23
- # def test_broadcasts
24
- # assert_broadcasts 'messages', 0
25
- # ActionCable.server.broadcast 'messages', { text: 'hello' }
26
- # assert_broadcasts 'messages', 1
27
- # ActionCable.server.broadcast 'messages', { text: 'world' }
28
- # assert_broadcasts 'messages', 2
29
- # end
30
- #
31
- # If a block is passed, that block should cause the specified number of
32
- # messages to be broadcasted.
23
+ # Asserts that the number of broadcasted messages to the stream matches the
24
+ # given number.
33
25
  #
34
- # def test_broadcasts_again
35
- # assert_broadcasts('messages', 1) do
26
+ # def test_broadcasts
27
+ # assert_broadcasts 'messages', 0
36
28
  # ActionCable.server.broadcast 'messages', { text: 'hello' }
29
+ # assert_broadcasts 'messages', 1
30
+ # ActionCable.server.broadcast 'messages', { text: 'world' }
31
+ # assert_broadcasts 'messages', 2
37
32
  # end
38
33
  #
39
- # assert_broadcasts('messages', 2) do
40
- # ActionCable.server.broadcast 'messages', { text: 'hi' }
41
- # ActionCable.server.broadcast 'messages', { text: 'how are you?' }
34
+ # If a block is passed, that block should cause the specified number of messages
35
+ # to be broadcasted.
36
+ #
37
+ # def test_broadcasts_again
38
+ # assert_broadcasts('messages', 1) do
39
+ # ActionCable.server.broadcast 'messages', { text: 'hello' }
40
+ # end
41
+ #
42
+ # assert_broadcasts('messages', 2) do
43
+ # ActionCable.server.broadcast 'messages', { text: 'hi' }
44
+ # ActionCable.server.broadcast 'messages', { text: 'how are you?' }
45
+ # end
42
46
  # end
43
- # end
44
47
  #
45
48
  def assert_broadcasts(stream, number, &block)
46
49
  if block_given?
@@ -56,23 +59,23 @@ module ActionCable
56
59
 
57
60
  # Asserts that no messages have been sent to the stream.
58
61
  #
59
- # def test_no_broadcasts
60
- # assert_no_broadcasts 'messages'
61
- # ActionCable.server.broadcast 'messages', { text: 'hi' }
62
- # assert_broadcasts 'messages', 1
63
- # end
62
+ # def test_no_broadcasts
63
+ # assert_no_broadcasts 'messages'
64
+ # ActionCable.server.broadcast 'messages', { text: 'hi' }
65
+ # assert_broadcasts 'messages', 1
66
+ # end
64
67
  #
65
68
  # If a block is passed, that block should not cause any message to be sent.
66
69
  #
67
- # def test_broadcasts_again
68
- # assert_no_broadcasts 'messages' do
69
- # # No job messages should be sent from this block
70
+ # def test_broadcasts_again
71
+ # assert_no_broadcasts 'messages' do
72
+ # # No job messages should be sent from this block
73
+ # end
70
74
  # end
71
- # end
72
75
  #
73
76
  # Note: This assertion is simply a shortcut for:
74
77
  #
75
- # assert_broadcasts 'messages', 0, &block
78
+ # assert_broadcasts 'messages', 0, &block
76
79
  #
77
80
  def assert_no_broadcasts(stream, &block)
78
81
  assert_broadcasts stream, 0, &block
@@ -80,15 +83,15 @@ module ActionCable
80
83
 
81
84
  # Returns the messages that are broadcasted in the block.
82
85
  #
83
- # def test_broadcasts
84
- # messages = capture_broadcasts('messages') do
85
- # ActionCable.server.broadcast 'messages', { text: 'hi' }
86
- # ActionCable.server.broadcast 'messages', { text: 'how are you?' }
86
+ # def test_broadcasts
87
+ # messages = capture_broadcasts('messages') do
88
+ # ActionCable.server.broadcast 'messages', { text: 'hi' }
89
+ # ActionCable.server.broadcast 'messages', { text: 'how are you?' }
90
+ # end
91
+ # assert_equal 2, messages.length
92
+ # assert_equal({ text: 'hi' }, messages.first)
93
+ # assert_equal({ text: 'how are you?' }, messages.last)
87
94
  # end
88
- # assert_equal 2, messages.length
89
- # assert_equal({ text: 'hi' }, messages.first)
90
- # assert_equal({ text: 'how are you?' }, messages.last)
91
- # end
92
95
  #
93
96
  def capture_broadcasts(stream, &block)
94
97
  new_broadcasts_from(broadcasts(stream), stream, "capture_broadcasts", &block).map { |m| ActiveSupport::JSON.decode(m) }
@@ -96,23 +99,23 @@ module ActionCable
96
99
 
97
100
  # Asserts that the specified message has been sent to the stream.
98
101
  #
99
- # def test_assert_transmitted_message
100
- # ActionCable.server.broadcast 'messages', text: 'hello'
101
- # assert_broadcast_on('messages', text: 'hello')
102
- # end
102
+ # def test_assert_transmitted_message
103
+ # ActionCable.server.broadcast 'messages', text: 'hello'
104
+ # assert_broadcast_on('messages', text: 'hello')
105
+ # end
103
106
  #
104
- # If a block is passed, that block should cause a message with the specified data to be sent.
107
+ # If a block is passed, that block should cause a message with the specified
108
+ # data to be sent.
105
109
  #
106
- # def test_assert_broadcast_on_again
107
- # assert_broadcast_on('messages', text: 'hello') do
108
- # ActionCable.server.broadcast 'messages', text: 'hello'
110
+ # def test_assert_broadcast_on_again
111
+ # assert_broadcast_on('messages', text: 'hello') do
112
+ # ActionCable.server.broadcast 'messages', text: 'hello'
113
+ # end
109
114
  # end
110
- # end
111
115
  #
112
116
  def assert_broadcast_on(stream, data, &block)
113
- # Encode to JSON and back–we want to use this value to compare
114
- # with decoded JSON.
115
- # Comparing JSON strings doesn't work due to the order if the keys.
117
+ # Encode to JSON and back–we want to use this value to compare with decoded
118
+ # JSON. Comparing JSON strings doesn't work due to the order if the keys.
116
119
  serialized_msg =
117
120
  ActiveSupport::JSON.decode(ActiveSupport::JSON.encode(data))
118
121
 
@@ -1,9 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  require_relative "gem_version"
4
6
 
5
7
  module ActionCable
6
- # Returns the currently loaded version of Action Cable as a +Gem::Version+.
8
+ # Returns the currently loaded version of Action Cable as a `Gem::Version`.
7
9
  def self.version
8
10
  gem_version
9
11
  end
data/lib/action_cable.rb CHANGED
@@ -27,17 +27,23 @@ require "active_support"
27
27
  require "active_support/rails"
28
28
  require "zeitwerk"
29
29
 
30
+ # We compute lib this way instead of using __dir__ because __dir__ gives a real
31
+ # path, while __FILE__ honors symlinks. If the gem is stored under a symlinked
32
+ # directory, this matters.
33
+ lib = File.dirname(__FILE__)
34
+
30
35
  Zeitwerk::Loader.for_gem.tap do |loader|
31
36
  loader.ignore(
32
- "#{__dir__}/rails", # Contains generators, templates, docs, etc.
33
- "#{__dir__}/action_cable/gem_version.rb",
34
- "#{__dir__}/action_cable/deprecator.rb",
37
+ "#{lib}/rails", # Contains generators, templates, docs, etc.
38
+ "#{lib}/action_cable/gem_version.rb",
39
+ "#{lib}/action_cable/version.rb",
40
+ "#{lib}/action_cable/deprecator.rb",
35
41
  )
36
42
 
37
43
  loader.do_not_eager_load(
38
- "#{__dir__}/action_cable/subscription_adapter", # Adapters are required and loaded on demand.
39
- "#{__dir__}/action_cable/test_helper.rb",
40
- Dir["#{__dir__}/action_cable/**/test_case.rb"]
44
+ "#{lib}/action_cable/subscription_adapter", # Adapters are required and loaded on demand.
45
+ "#{lib}/action_cable/test_helper.rb",
46
+ Dir["#{lib}/action_cable/**/test_case.rb"]
41
47
  )
42
48
 
43
49
  loader.inflector.inflect("postgresql" => "PostgreSQL")
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  module Rails
4
6
  module Generators
5
7
  class ChannelGenerator < NamedBase
@@ -103,8 +105,8 @@ pin_all_from "app/javascript/channels", under: "channels"
103
105
  end
104
106
 
105
107
  def using_bun?
106
- # Cannot assume bun.lockb has been generated yet so we look for
107
- # a file known to be generated by the jsbundling-rails gem
108
+ # Cannot assume bun.lockb has been generated yet so we look for a file known to
109
+ # be generated by the jsbundling-rails gem
108
110
  @using_bun ||= using_js_runtime? && root.join("bun.config.js").exist?
109
111
  end
110
112
 
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # :markup: markdown
4
+
3
5
  module TestUnit
4
6
  module Generators
5
7
  class ChannelGenerator < ::Rails::Generators::NamedBase
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: actioncable
3
3
  version: !ruby/object:Gem::Version
4
- version: 7.1.5.1
4
+ version: 7.2.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Pratik Naik
@@ -17,28 +17,28 @@ dependencies:
17
17
  requirements:
18
18
  - - '='
19
19
  - !ruby/object:Gem::Version
20
- version: 7.1.5.1
20
+ version: 7.2.2.1
21
21
  type: :runtime
22
22
  prerelease: false
23
23
  version_requirements: !ruby/object:Gem::Requirement
24
24
  requirements:
25
25
  - - '='
26
26
  - !ruby/object:Gem::Version
27
- version: 7.1.5.1
27
+ version: 7.2.2.1
28
28
  - !ruby/object:Gem::Dependency
29
29
  name: actionpack
30
30
  requirement: !ruby/object:Gem::Requirement
31
31
  requirements:
32
32
  - - '='
33
33
  - !ruby/object:Gem::Version
34
- version: 7.1.5.1
34
+ version: 7.2.2.1
35
35
  type: :runtime
36
36
  prerelease: false
37
37
  version_requirements: !ruby/object:Gem::Requirement
38
38
  requirements:
39
39
  - - '='
40
40
  - !ruby/object:Gem::Version
41
- version: 7.1.5.1
41
+ version: 7.2.2.1
42
42
  - !ruby/object:Gem::Dependency
43
43
  name: nio4r
44
44
  requirement: !ruby/object:Gem::Requirement
@@ -141,8 +141,8 @@ files:
141
141
  - lib/action_cable/version.rb
142
142
  - lib/rails/generators/channel/USAGE
143
143
  - lib/rails/generators/channel/channel_generator.rb
144
- - lib/rails/generators/channel/templates/application_cable/channel.rb
145
- - lib/rails/generators/channel/templates/application_cable/connection.rb
144
+ - lib/rails/generators/channel/templates/application_cable/channel.rb.tt
145
+ - lib/rails/generators/channel/templates/application_cable/connection.rb.tt
146
146
  - lib/rails/generators/channel/templates/channel.rb.tt
147
147
  - lib/rails/generators/channel/templates/javascript/channel.js.tt
148
148
  - lib/rails/generators/channel/templates/javascript/consumer.js.tt
@@ -154,10 +154,10 @@ licenses:
154
154
  - MIT
155
155
  metadata:
156
156
  bug_tracker_uri: https://github.com/rails/rails/issues
157
- changelog_uri: https://github.com/rails/rails/blob/v7.1.5.1/actioncable/CHANGELOG.md
158
- documentation_uri: https://api.rubyonrails.org/v7.1.5.1/
157
+ changelog_uri: https://github.com/rails/rails/blob/v7.2.2.1/actioncable/CHANGELOG.md
158
+ documentation_uri: https://api.rubyonrails.org/v7.2.2.1/
159
159
  mailing_list_uri: https://discuss.rubyonrails.org/c/rubyonrails-talk
160
- source_code_uri: https://github.com/rails/rails/tree/v7.1.5.1/actioncable
160
+ source_code_uri: https://github.com/rails/rails/tree/v7.2.2.1/actioncable
161
161
  rubygems_mfa_required: 'true'
162
162
  post_install_message:
163
163
  rdoc_options: []
@@ -167,7 +167,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
167
167
  requirements:
168
168
  - - ">="
169
169
  - !ruby/object:Gem::Version
170
- version: 2.7.0
170
+ version: 3.1.0
171
171
  required_rubygems_version: !ruby/object:Gem::Requirement
172
172
  requirements:
173
173
  - - ">="