anycable-rails-core 1.6.0.rc.1 → 1.6.0.rc.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 +13 -1
- data/lib/anycable/rails/action_cable_ext/channel.rb +0 -11
- data/lib/anycable/rails/channel/presence.rb +1 -1
- data/lib/anycable/rails/connection.rb +58 -33
- data/lib/anycable/rails/helper.rb +2 -2
- data/lib/anycable/rails/version.rb +1 -1
- data/lib/generators/anycable/download/download_generator.rb +16 -5
- data/lib/generators/anycable/setup/setup_generator.rb +18 -0
- metadata +5 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 734dca7d3a224a971ba2e4979e0a33337fa4551ff07cb86acd3c6cc546eea974
|
4
|
+
data.tar.gz: 88d96b3f0c85a2259c29cb0f863cdcee92584b801309202cab4a9d03c8152710
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5b0d2f5faf24b406264326771b00b23aadc88cb6b20d62a9055857e31c5e99d6cc770dc835dfabfff66c65aa26768062197c8d67d1e357749f0563d214d2cc30
|
7
|
+
data.tar.gz: 2793659e6c349ef838a84e57b4d42b3ddcff7aeabfb9024207e1e8a08b09e85ff28e68aaa1693b4e174512a03ddd0c7cc11450a988470846add034d31742f0b4
|
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,18 @@
|
|
1
1
|
# Change log
|
2
2
|
|
3
|
-
##
|
3
|
+
## main
|
4
|
+
|
5
|
+
## 1.6.0.rc.3 (2025-02-20)
|
6
|
+
|
7
|
+
- Update `anycable:download` generator to support v1.6+. ([@palkan][])
|
8
|
+
|
9
|
+
- Add `#anycable_token_meta_tag` helper. ([@palkan][])
|
10
|
+
|
11
|
+
It generates a meta tag with the AnyCable JWT token (w/o the URL).
|
12
|
+
|
13
|
+
## 1.6.0.rc.2 (2025-02-10)
|
14
|
+
|
15
|
+
- Add Presence API. ([@palkan][])
|
4
16
|
|
5
17
|
## 1.5.5 (2024-12-12)
|
6
18
|
|
@@ -3,17 +3,6 @@
|
|
3
3
|
require "action_cable"
|
4
4
|
|
5
5
|
ActionCable::Channel::Base.prepend(Module.new do
|
6
|
-
def subscribe_to_channel
|
7
|
-
super unless anycabled? && !@__anycable_subscribing__
|
8
|
-
end
|
9
|
-
|
10
|
-
def handle_subscribe
|
11
|
-
@__anycable_subscribing__ = true
|
12
|
-
subscribe_to_channel
|
13
|
-
ensure
|
14
|
-
@__anycable_subscribing__ = false
|
15
|
-
end
|
16
|
-
|
17
6
|
def start_periodic_timers
|
18
7
|
super unless anycabled?
|
19
8
|
end
|
@@ -12,7 +12,7 @@ module AnyCable
|
|
12
12
|
|
13
13
|
stream ||= connection.anycable_socket.streams[:start].first || raise(ArgumentError, "Provide a stream name for presence updates")
|
14
14
|
|
15
|
-
connection.anycable_socket.presence_join(stream, id, info)
|
15
|
+
connection.anycable_socket.presence_join(stream, id.to_s, info)
|
16
16
|
end
|
17
17
|
|
18
18
|
def leave_presence(id = user_presence_id)
|
@@ -31,15 +31,65 @@ module AnyCable
|
|
31
31
|
end
|
32
32
|
|
33
33
|
refine ActionCable::Connection::Subscriptions do
|
34
|
-
#
|
35
|
-
|
36
|
-
|
34
|
+
# Override the original #execute_command to pre-initialize the channel for unsubscribe/message and
|
35
|
+
# return true/false to indicate successful/unsuccessful subscription.
|
36
|
+
# We also must not lose any exceptions raised in the process.
|
37
|
+
def execute_rpc_command(data)
|
38
|
+
# First, verify the channel name
|
39
|
+
raise "Channel not found: #{ActiveSupport::JSON.decode(data["identifier"]).fetch("channel")}" unless subscription_class_from_identifier(data["identifier"])
|
40
|
+
|
41
|
+
if data["command"] == "subscribe"
|
42
|
+
add data
|
43
|
+
subscription = subscriptions[data["identifier"]]
|
44
|
+
return !(subscription.nil? || subscription.rejected?)
|
45
|
+
end
|
46
|
+
|
47
|
+
load(data["identifier"])
|
37
48
|
|
38
|
-
|
39
|
-
|
49
|
+
case data["command"]
|
50
|
+
when "unsubscribe"
|
51
|
+
remove data
|
52
|
+
when "message"
|
53
|
+
perform_action data
|
54
|
+
when "whisper"
|
55
|
+
whisper data
|
56
|
+
else
|
57
|
+
raise UnknownCommandError, data["command"]
|
40
58
|
end
|
41
59
|
|
42
|
-
|
60
|
+
true
|
61
|
+
end
|
62
|
+
|
63
|
+
# Restore channels from the list of identifiers and the state
|
64
|
+
def restore(subscriptions, istate)
|
65
|
+
subscriptions.each do |id|
|
66
|
+
channel = load(id)
|
67
|
+
channel.__istate__ = ActiveSupport::JSON.decode(istate[id]) if istate[id]
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
# Find or create a channel for a given identifier
|
72
|
+
def load(identifier)
|
73
|
+
return subscriptions[identifier] if subscriptions[identifier]
|
74
|
+
|
75
|
+
subscription = subscription_from_identifier(identifier)
|
76
|
+
raise "Channel not found: #{ActiveSupport::JSON.decode(identifier).fetch("channel")}" unless subscription
|
77
|
+
|
78
|
+
subscriptions[identifier] = subscription
|
79
|
+
end
|
80
|
+
|
81
|
+
def subscription_class_from_identifier(id_key)
|
82
|
+
id_options = ActiveSupport::JSON.decode(id_key).with_indifferent_access
|
83
|
+
id_options[:channel].safe_constantize
|
84
|
+
end
|
85
|
+
|
86
|
+
def subscription_from_identifier(id_key)
|
87
|
+
subscription_klass = subscription_class_from_identifier(id_key)
|
88
|
+
|
89
|
+
if subscription_klass && subscription_klass < ActionCable::Channel::Base
|
90
|
+
id_options = ActiveSupport::JSON.decode(id_key).with_indifferent_access
|
91
|
+
subscription_klass.new(connection, id_key, id_options)
|
92
|
+
end
|
43
93
|
end
|
44
94
|
end
|
45
95
|
end)
|
@@ -74,15 +124,8 @@ module AnyCable
|
|
74
124
|
conn.cached_ids = {}
|
75
125
|
conn.anycable_request_builder = self
|
76
126
|
|
77
|
-
return unless subscriptions
|
78
|
-
|
79
127
|
# Pre-initialize channels (for disconnect)
|
80
|
-
subscriptions.
|
81
|
-
channel = conn.subscriptions.fetch(id)
|
82
|
-
next unless socket.istate[id]
|
83
|
-
|
84
|
-
channel.__istate__ = ActiveSupport::JSON.decode(socket.istate[id])
|
85
|
-
end
|
128
|
+
conn.subscriptions.restore(subscriptions, socket.istate) if subscriptions
|
86
129
|
end
|
87
130
|
|
88
131
|
def handle_open
|
@@ -111,26 +154,8 @@ module AnyCable
|
|
111
154
|
|
112
155
|
def handle_channel_command(identifier, command, data)
|
113
156
|
conn.run_callbacks :command do
|
114
|
-
|
115
|
-
# since we MUST return true of false, depending on the status
|
116
|
-
# of execution
|
117
|
-
channel = conn.subscriptions.fetch(identifier)
|
118
|
-
case command
|
119
|
-
when "subscribe"
|
120
|
-
channel.handle_subscribe
|
121
|
-
!channel.rejected?
|
122
|
-
when "unsubscribe"
|
123
|
-
conn.subscriptions.remove_subscription(channel)
|
124
|
-
true
|
125
|
-
when "message"
|
126
|
-
channel.perform_action ActiveSupport::JSON.decode(data)
|
127
|
-
true
|
128
|
-
else
|
129
|
-
false
|
130
|
-
end
|
157
|
+
conn.subscriptions.execute_rpc_command({"command" => command, "identifier" => identifier, "data" => data})
|
131
158
|
end
|
132
|
-
# Support rescue_from
|
133
|
-
# https://github.com/rails/rails/commit/d2571e560c62116f60429c933d0c41a0e249b58b
|
134
159
|
rescue Exception => e # rubocop:disable Lint/RescueException
|
135
160
|
rescue_with_handler(e) || raise
|
136
161
|
false
|
@@ -22,10 +22,10 @@ module AnyCable
|
|
22
22
|
tag "meta", name: "action-cable-url", content: url
|
23
23
|
end
|
24
24
|
|
25
|
-
def
|
25
|
+
def anycable_token_meta_tag(**identifiers)
|
26
26
|
token = JWT.encode(identifiers)
|
27
27
|
|
28
|
-
tag "meta", name: "
|
28
|
+
tag "meta", name: "cable-token", content: token
|
29
29
|
end
|
30
30
|
|
31
31
|
def signed_stream_name(streamables)
|
@@ -37,24 +37,35 @@ module AnyCableRailsGenerators
|
|
37
37
|
return latest_release_url(version) if version == "latest"
|
38
38
|
|
39
39
|
if Gem::Version.new(version).segments.first >= 1
|
40
|
-
new_release_url(
|
40
|
+
new_release_url(version)
|
41
41
|
else
|
42
|
-
legacy_release_url(
|
42
|
+
legacy_release_url(version)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def repository_name(version)
|
47
|
+
return "anycable/anycable" if version == "latest"
|
48
|
+
|
49
|
+
major, minor, = Gem::Version.new(version).segments
|
50
|
+
if (major >= 1 && minor >= 6) || (major > 1)
|
51
|
+
"anycable/anycable"
|
52
|
+
else
|
53
|
+
"anycable/anycable-go"
|
43
54
|
end
|
44
55
|
end
|
45
56
|
|
46
57
|
def legacy_release_url(version)
|
47
|
-
"https://github.com/
|
58
|
+
"https://github.com/#{repository_name(version)}/releases/download/v#{version}/" \
|
48
59
|
"anycable-go-v#{version}-#{os_name}-#{cpu_name}"
|
49
60
|
end
|
50
61
|
|
51
62
|
def new_release_url(version)
|
52
|
-
"https://github.com/
|
63
|
+
"https://github.com/#{repository_name(version)}/releases/download/v#{version}/" \
|
53
64
|
"anycable-go-#{os_name}-#{cpu_name}"
|
54
65
|
end
|
55
66
|
|
56
67
|
def latest_release_url(version)
|
57
|
-
"https://github.com/
|
68
|
+
"https://github.com/#{repository_name(version)}/releases/latest/download/" \
|
58
69
|
"anycable-go-#{os_name}-#{cpu_name}"
|
59
70
|
end
|
60
71
|
|
@@ -88,6 +88,13 @@ module AnyCableRailsGenerators
|
|
88
88
|
"`action_cable_meta_tag` or `action_cable_with_jwt_meta_tag` included in your HTML layout"
|
89
89
|
end
|
90
90
|
|
91
|
+
def cable_engine_warning
|
92
|
+
return unless application_rb
|
93
|
+
return if application_rb.match?(/^require\s+['"](action_cable\/engine|rails\/all)['"]/)
|
94
|
+
|
95
|
+
say_status :help, "⚠️ Ensure Action Cable is loaded.\nAdd `require \"action_cable/engine\"` to your `config/application.rb`."
|
96
|
+
end
|
97
|
+
|
91
98
|
def deployment_method
|
92
99
|
say_status :info, "🚢 See our deployment guide to learn how to run AnyCable in production 👉 #{DOCS_ROOT}/deployment"
|
93
100
|
|
@@ -139,6 +146,17 @@ module AnyCableRailsGenerators
|
|
139
146
|
end
|
140
147
|
end
|
141
148
|
|
149
|
+
def application_rb
|
150
|
+
@application_rb ||= begin
|
151
|
+
res = nil
|
152
|
+
in_root do
|
153
|
+
next unless File.file?("config/application.rb")
|
154
|
+
res = File.read("config/application.rb")
|
155
|
+
end
|
156
|
+
res
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
142
160
|
def install_for_docker
|
143
161
|
say_status :help, "️️⚠️ Docker development configuration could vary", :yellow
|
144
162
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: anycable-rails-core
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.6.0.rc.
|
4
|
+
version: 1.6.0.rc.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- palkan
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-
|
11
|
+
date: 2025-02-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: anycable-core
|
@@ -139,7 +139,7 @@ metadata:
|
|
139
139
|
homepage_uri: https://anycable.io/
|
140
140
|
source_code_uri: http://github.com/anycable/anycable-rails
|
141
141
|
funding_uri: https://github.com/sponsors/anycable
|
142
|
-
post_install_message:
|
142
|
+
post_install_message:
|
143
143
|
rdoc_options: []
|
144
144
|
require_paths:
|
145
145
|
- lib
|
@@ -155,7 +155,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
155
155
|
version: 1.3.1
|
156
156
|
requirements: []
|
157
157
|
rubygems_version: 3.4.19
|
158
|
-
signing_key:
|
158
|
+
signing_key:
|
159
159
|
specification_version: 4
|
160
160
|
summary: AnyCable integration for Rails (w/o RPC dependencies)
|
161
161
|
test_files: []
|