actioncable 7.1.3.3 → 7.2.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +15 -136
- 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 +98 -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 +77 -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 -56
- 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 +4 -2
- data/lib/action_cable/subscription_adapter/redis.rb +5 -2
- 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 -52
- data/lib/action_cable/version.rb +3 -1
- data/lib/action_cable.rb +2 -1
- data/lib/rails/generators/channel/channel_generator.rb +4 -2
- data/lib/rails/generators/channel/templates/application_cable/channel.rb +2 -0
- data/lib/rails/generators/channel/templates/application_cable/connection.rb +2 -0
- data/lib/rails/generators/test_unit/channel_generator.rb +2 -0
- metadata +10 -10
@@ -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
|
-
#
|
7
|
+
# # Action Cable Server Connections
|
6
8
|
#
|
7
|
-
# Collection class for all the connections that have been established on this
|
8
|
-
#
|
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
|
25
|
-
#
|
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
|
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
|
-
#
|
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
|
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
|
-
#
|
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
|
14
|
-
# This is needed, for example, when
|
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,16 +1,19 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
# :markup: markdown
|
4
|
+
|
3
5
|
module ActionCable
|
4
6
|
module SubscriptionAdapter
|
5
|
-
#
|
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
|
10
|
+
# ActionCable::TestHelper it makes a great tool to test your Rails application.
|
9
11
|
#
|
10
|
-
# To use the test adapter set
|
12
|
+
# To use the test adapter set `adapter` value to `test` in your
|
13
|
+
# `config/cable.yml` file.
|
11
14
|
#
|
12
|
-
# NOTE:
|
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
|
module ActionCable
|
4
6
|
# Provides helper methods for testing Action Cable broadcasting
|
5
7
|
module TestHelper
|
@@ -18,33 +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
|
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. It returns the messages that were broadcasted.
|
23
|
+
# Asserts that the number of broadcasted messages to the stream matches the
|
24
|
+
# given number.
|
33
25
|
#
|
34
|
-
#
|
35
|
-
#
|
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
|
-
# assert_equal({ text: 'hello' }, message)
|
39
33
|
#
|
40
|
-
#
|
41
|
-
#
|
42
|
-
#
|
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
|
43
46
|
# end
|
44
|
-
# assert_equal 2, messages.length
|
45
|
-
# assert_equal({ text: 'hi' }, messages.first)
|
46
|
-
# assert_equal({ text: 'how are you?' }, messages.last)
|
47
|
-
# end
|
48
47
|
#
|
49
48
|
def assert_broadcasts(stream, number, &block)
|
50
49
|
if block_given?
|
@@ -60,23 +59,23 @@ module ActionCable
|
|
60
59
|
|
61
60
|
# Asserts that no messages have been sent to the stream.
|
62
61
|
#
|
63
|
-
#
|
64
|
-
#
|
65
|
-
#
|
66
|
-
#
|
67
|
-
#
|
62
|
+
# def test_no_broadcasts
|
63
|
+
# assert_no_broadcasts 'messages'
|
64
|
+
# ActionCable.server.broadcast 'messages', { text: 'hi' }
|
65
|
+
# assert_broadcasts 'messages', 1
|
66
|
+
# end
|
68
67
|
#
|
69
68
|
# If a block is passed, that block should not cause any message to be sent.
|
70
69
|
#
|
71
|
-
#
|
72
|
-
#
|
73
|
-
#
|
70
|
+
# def test_broadcasts_again
|
71
|
+
# assert_no_broadcasts 'messages' do
|
72
|
+
# # No job messages should be sent from this block
|
73
|
+
# end
|
74
74
|
# end
|
75
|
-
# end
|
76
75
|
#
|
77
76
|
# Note: This assertion is simply a shortcut for:
|
78
77
|
#
|
79
|
-
#
|
78
|
+
# assert_broadcasts 'messages', 0, &block
|
80
79
|
#
|
81
80
|
def assert_no_broadcasts(stream, &block)
|
82
81
|
assert_broadcasts stream, 0, &block
|
@@ -84,15 +83,15 @@ module ActionCable
|
|
84
83
|
|
85
84
|
# Returns the messages that are broadcasted in the block.
|
86
85
|
#
|
87
|
-
#
|
88
|
-
#
|
89
|
-
#
|
90
|
-
#
|
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)
|
91
94
|
# end
|
92
|
-
# assert_equal 2, messages.length
|
93
|
-
# assert_equal({ text: 'hi' }, messages.first)
|
94
|
-
# assert_equal({ text: 'how are you?' }, messages.last)
|
95
|
-
# end
|
96
95
|
#
|
97
96
|
def capture_broadcasts(stream, &block)
|
98
97
|
new_broadcasts_from(broadcasts(stream), stream, "capture_broadcasts", &block).map { |m| ActiveSupport::JSON.decode(m) }
|
@@ -100,23 +99,23 @@ module ActionCable
|
|
100
99
|
|
101
100
|
# Asserts that the specified message has been sent to the stream.
|
102
101
|
#
|
103
|
-
#
|
104
|
-
#
|
105
|
-
#
|
106
|
-
#
|
102
|
+
# def test_assert_transmitted_message
|
103
|
+
# ActionCable.server.broadcast 'messages', text: 'hello'
|
104
|
+
# assert_broadcast_on('messages', text: 'hello')
|
105
|
+
# end
|
107
106
|
#
|
108
|
-
# If a block is passed, that block should cause a message with the specified
|
107
|
+
# If a block is passed, that block should cause a message with the specified
|
108
|
+
# data to be sent.
|
109
109
|
#
|
110
|
-
#
|
111
|
-
#
|
112
|
-
#
|
110
|
+
# def test_assert_broadcast_on_again
|
111
|
+
# assert_broadcast_on('messages', text: 'hello') do
|
112
|
+
# ActionCable.server.broadcast 'messages', text: 'hello'
|
113
|
+
# end
|
113
114
|
# end
|
114
|
-
# end
|
115
115
|
#
|
116
116
|
def assert_broadcast_on(stream, data, &block)
|
117
|
-
# Encode to JSON and back–we want to use this value to compare
|
118
|
-
#
|
119
|
-
# 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.
|
120
119
|
serialized_msg =
|
121
120
|
ActiveSupport::JSON.decode(ActiveSupport::JSON.encode(data))
|
122
121
|
|
data/lib/action_cable/version.rb
CHANGED
@@ -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
|
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
@@ -31,6 +31,7 @@ Zeitwerk::Loader.for_gem.tap do |loader|
|
|
31
31
|
loader.ignore(
|
32
32
|
"#{__dir__}/rails", # Contains generators, templates, docs, etc.
|
33
33
|
"#{__dir__}/action_cable/gem_version.rb",
|
34
|
+
"#{__dir__}/action_cable/version.rb",
|
34
35
|
"#{__dir__}/action_cable/deprecator.rb",
|
35
36
|
)
|
36
37
|
|
@@ -44,7 +45,7 @@ Zeitwerk::Loader.for_gem.tap do |loader|
|
|
44
45
|
end.setup
|
45
46
|
|
46
47
|
# :markup: markdown
|
47
|
-
# :include:
|
48
|
+
# :include: ../README.md
|
48
49
|
module ActionCable
|
49
50
|
require_relative "action_cable/version"
|
50
51
|
require_relative "action_cable/deprecator"
|
@@ -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
|
-
#
|
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
|
|
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.
|
4
|
+
version: 7.2.0.beta1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Pratik Naik
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2024-05-
|
12
|
+
date: 2024-05-29 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activesupport
|
@@ -17,28 +17,28 @@ dependencies:
|
|
17
17
|
requirements:
|
18
18
|
- - '='
|
19
19
|
- !ruby/object:Gem::Version
|
20
|
-
version: 7.
|
20
|
+
version: 7.2.0.beta1
|
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.
|
27
|
+
version: 7.2.0.beta1
|
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.
|
34
|
+
version: 7.2.0.beta1
|
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.
|
41
|
+
version: 7.2.0.beta1
|
42
42
|
- !ruby/object:Gem::Dependency
|
43
43
|
name: nio4r
|
44
44
|
requirement: !ruby/object:Gem::Requirement
|
@@ -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.
|
158
|
-
documentation_uri: https://api.rubyonrails.org/v7.
|
157
|
+
changelog_uri: https://github.com/rails/rails/blob/v7.2.0.beta1/actioncable/CHANGELOG.md
|
158
|
+
documentation_uri: https://api.rubyonrails.org/v7.2.0.beta1/
|
159
159
|
mailing_list_uri: https://discuss.rubyonrails.org/c/rubyonrails-talk
|
160
|
-
source_code_uri: https://github.com/rails/rails/tree/v7.
|
160
|
+
source_code_uri: https://github.com/rails/rails/tree/v7.2.0.beta1/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:
|
170
|
+
version: 3.1.0
|
171
171
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
172
172
|
requirements:
|
173
173
|
- - ">="
|