anycable-rails-core 1.5.4 → 1.6.2
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 +25 -1
- data/README.md +10 -71
- data/lib/anycable/rails/action_cable_ext/channel.rb +0 -11
- data/lib/anycable/rails/action_cable_ext/remote_connections.rb +1 -1
- data/lib/anycable/rails/channel/presence.rb +36 -0
- data/lib/anycable/rails/channel.rb +9 -0
- data/lib/anycable/rails/compatibility/rubocop.rb +2 -25
- data/lib/anycable/rails/compatibility.rb +1 -0
- data/lib/anycable/rails/config.rb +2 -0
- data/lib/anycable/rails/connection.rb +62 -33
- data/lib/anycable/rails/connections/serializable_identification.rb +14 -0
- data/lib/anycable/rails/helper.rb +2 -2
- data/lib/anycable/rails/railtie.rb +4 -2
- data/lib/anycable/rails/{compatibility/rubocop → rubocop}/cops/anycable/instance_vars.rb +1 -1
- data/lib/anycable/rails/{compatibility/rubocop → rubocop}/cops/anycable/periodical_timers.rb +3 -8
- data/lib/anycable/rails/{compatibility/rubocop → rubocop}/cops/anycable/stream_from.rb +3 -5
- data/lib/anycable/rails/rubocop.rb +27 -0
- data/lib/anycable/rails/socket_id_tracking.rb +2 -2
- data/lib/anycable/rails/version.rb +1 -1
- data/lib/anycable/rails.rb +2 -1
- data/lib/generators/anycable/bin/templates/bin/anycable-go.tt +5 -0
- data/lib/generators/anycable/download/download_generator.rb +16 -5
- data/lib/generators/anycable/setup/setup_generator.rb +278 -33
- data/lib/generators/anycable/setup/templates/Procfile.dev.tt +2 -2
- data/lib/generators/anycable/setup/templates/anycable.toml.tt +40 -42
- data/lib/generators/anycable/setup/templates/bin/anycable-go.tt +5 -0
- data/lib/generators/anycable/setup/templates/bin/dev +17 -0
- data/lib/generators/anycable/setup/templates/config/anycable.yml.tt +18 -35
- data/lib/generators/anycable/setup/templates/config/cable.yml.tt +2 -5
- metadata +16 -11
- /data/lib/anycable/rails/{compatibility/rubocop → rubocop}/config/default.yml +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ae5f5e00ae334a317de5b59685ff57de668c2f102125f48bc8309a7330787950
|
|
4
|
+
data.tar.gz: f15f057412a3c0a0dbf759bd8c8d47abee1bee60a9b68ca62983ced577ea9397
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 8b780c7ca124e8f84d708e94ec78a27b50e9b36cbf524264cea3582bb171b037e40f4f92d8292f115810b988dfe93d45a942c779550943484bfad9810c1865f3
|
|
7
|
+
data.tar.gz: 916571c822234a92ec9bbb1839c06c8a0cc9a6f434c370c0b9bccd6486a450c2dc2ec88e27069d3b14bff093e245d0a83e6aed71fc7bcd1f20b298ae479edde7
|
data/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,30 @@
|
|
|
1
1
|
# Change log
|
|
2
2
|
|
|
3
|
-
##
|
|
3
|
+
## main
|
|
4
|
+
|
|
5
|
+
## 1.6.2 (2026-04-02)
|
|
6
|
+
|
|
7
|
+
- Upgrade setup generator. ([@palkan][])
|
|
8
|
+
|
|
9
|
+
## 1.6.1 (2025-12-18)
|
|
10
|
+
|
|
11
|
+
- Ensure `bin/dist/anycable-go` has execution permission as part of `bin/anycable-go` ([@dmorgan-fa][])
|
|
12
|
+
|
|
13
|
+
## 1.6.0 (2025-03-18)
|
|
14
|
+
|
|
15
|
+
- Update `anycable:download` generator to support v1.6+. ([@palkan][])
|
|
16
|
+
|
|
17
|
+
- Add `#anycable_token_meta_tag` helper. ([@palkan][])
|
|
18
|
+
|
|
19
|
+
It generates a meta tag with the AnyCable JWT token (w/o the URL).
|
|
20
|
+
|
|
21
|
+
- Add Presence API. ([@palkan][])
|
|
22
|
+
|
|
23
|
+
## 1.5.5 (2024-12-12)
|
|
24
|
+
|
|
25
|
+
- Publish RuboCop cops as a separate gem (`rubocop-anycable-rails`). ([@palkan][])
|
|
26
|
+
|
|
27
|
+
- Upgrade RuboCop cops. ([@palkan][])
|
|
4
28
|
|
|
5
29
|
## 1.5.4 (2024-10-08)
|
|
6
30
|
|
data/README.md
CHANGED
|
@@ -1,30 +1,18 @@
|
|
|
1
|
-
[](https://rubygems.org/gems/anycable)
|
|
2
2
|
[](https://github.com/anycable/anycable-rails/actions)
|
|
3
3
|
[](https://docs.anycable.io/rails/getting_started)
|
|
4
4
|
|
|
5
|
-
# AnyCable Rails
|
|
5
|
+
# AnyCable SDK for Ruby on Rails
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
<img align="right" height="150" width="129"
|
|
8
|
+
title="AnyCable logo" src="https://docs.anycable.io/assets/images/logo.svg">
|
|
8
9
|
|
|
9
|
-
|
|
10
|
+
[AnyCable](https://github.com/anycable/anycable) is an open-source language-agnostic realtime server for reliable two-way communication over WebSockets and SSE.
|
|
11
|
+
This repository contains code for AnyCable Rails SKD that allows you to use AnyCable as a drop-in replacement for Action Cable.
|
|
10
12
|
|
|
11
|
-
💾 [Example Application](https://github.com/anycable/anycable_rails_demo)
|
|
13
|
+
🌐 [Website](https://anycable.io) · 📚 [Documentation](https://docs.anycable.io/rails/getting_started) · 💾 [Example Rails Application](https://github.com/anycable/anycable_rails_demo)
|
|
12
14
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
> [AnyCable Pro](https://docs.anycable.io/pro) has been launched 🚀
|
|
16
|
-
|
|
17
|
-
<a href="https://evilmartians.com/">
|
|
18
|
-
<img src="https://evilmartians.com/badges/sponsored-by-evil-martians.svg" alt="Sponsored by Evil Martians" width="236" height="54"></a>
|
|
19
|
-
|
|
20
|
-
## Requirements
|
|
21
|
-
|
|
22
|
-
- Ruby >= 3.1
|
|
23
|
-
- Rails >= 6.0\*
|
|
24
|
-
|
|
25
|
-
\* Recent `anycable-rails` versions only work with Rails 8+; older versions compatible with Rails 6 and Rails 7 still receive fixes and minor updates (patch releases).
|
|
26
|
-
|
|
27
|
-
## Usage
|
|
15
|
+
## Quick Start
|
|
28
16
|
|
|
29
17
|
Add `anycable-rails` gem to your Gemfile:
|
|
30
18
|
|
|
@@ -32,62 +20,13 @@ Add `anycable-rails` gem to your Gemfile:
|
|
|
32
20
|
gem "anycable-rails"
|
|
33
21
|
```
|
|
34
22
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
After the gem was installed, you can run an interactive wizard to configure your Rails application for using with AnyCable by running a generator:
|
|
23
|
+
Then run our interactive setup command:
|
|
38
24
|
|
|
39
25
|
```sh
|
|
40
26
|
bundle exec rails g anycable:setup
|
|
41
27
|
```
|
|
42
28
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
Specify AnyCable subscription adapter for Action Cable:
|
|
46
|
-
|
|
47
|
-
```yml
|
|
48
|
-
# config/cable.yml
|
|
49
|
-
development:
|
|
50
|
-
adapter: any_cable # or anycable
|
|
51
|
-
|
|
52
|
-
production:
|
|
53
|
-
adapter: any_cable
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
and specify AnyCable WebSocket server URL:
|
|
57
|
-
|
|
58
|
-
```ruby
|
|
59
|
-
# For development it's likely the localhost
|
|
60
|
-
|
|
61
|
-
# config/environments/development.rb
|
|
62
|
-
config.action_cable.url = "ws://localhost:8080/cable"
|
|
63
|
-
|
|
64
|
-
# For production it's likely to have a sub-domain and secure connection
|
|
65
|
-
|
|
66
|
-
# config/environments/production.rb
|
|
67
|
-
config.action_cable.url = "wss://ws.example.com/cable"
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
Then, run AnyCable RPC server:
|
|
71
|
-
|
|
72
|
-
```sh
|
|
73
|
-
$ bundle exec anycable
|
|
74
|
-
|
|
75
|
-
# don't forget to provide Rails env
|
|
76
|
-
|
|
77
|
-
$ RAILS_ENV=production bundle exec anycable
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
And, finally, run AnyCable WebSocket server, e.g. [anycable-go](https://docs.anycable.io/anycable-go/getting_started):
|
|
81
|
-
|
|
82
|
-
```sh
|
|
83
|
-
anycable-go --host=localhost --port=8080
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
See [documentation](https://docs.anycable.io/rails/getting_started) for more information on AnyCable + Rails usage.
|
|
87
|
-
|
|
88
|
-
## Action Cable Compatibility
|
|
89
|
-
|
|
90
|
-
See [documentation](https://docs.anycable.io/rails/compatibility).
|
|
29
|
+
Learn more [here](https://docs.anycable.io/rails/getting_started).
|
|
91
30
|
|
|
92
31
|
## Contributing
|
|
93
32
|
|
|
@@ -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
|
|
@@ -6,7 +6,7 @@ ActionCable::RemoteConnections::RemoteConnection.include(AnyCable::Rails::Connec
|
|
|
6
6
|
ActionCable::RemoteConnections::RemoteConnection.prepend(Module.new do
|
|
7
7
|
def disconnect(reconnect: true)
|
|
8
8
|
# Legacy Action Cable functionality if case we're not fully migrated yet
|
|
9
|
-
super unless AnyCable::Rails.enabled?
|
|
9
|
+
return super unless AnyCable::Rails.enabled?
|
|
10
10
|
::AnyCable.broadcast_adapter.broadcast_command("disconnect", identifier: identifiers_json, reconnect: reconnect)
|
|
11
11
|
end
|
|
12
12
|
end)
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module AnyCable
|
|
4
|
+
module Rails
|
|
5
|
+
module Channel
|
|
6
|
+
# Presence API for Action Cable channels (backed by AnyCable)
|
|
7
|
+
module Presence
|
|
8
|
+
extend ActiveSupport::Concern
|
|
9
|
+
|
|
10
|
+
def join_presence(stream = nil, id: user_presence_id, info: user_presence_info)
|
|
11
|
+
return unless anycabled?
|
|
12
|
+
|
|
13
|
+
stream ||= connection.anycable_socket.streams[:start].first || raise(ArgumentError, "Provide a stream name for presence updates")
|
|
14
|
+
|
|
15
|
+
connection.anycable_socket.presence_join(stream, id.to_s, info)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def leave_presence(id = user_presence_id)
|
|
19
|
+
return unless anycabled?
|
|
20
|
+
|
|
21
|
+
connection.anycable_socket.presence_leave(id)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
private
|
|
25
|
+
|
|
26
|
+
def user_presence_id
|
|
27
|
+
connection.connection_identifier
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def user_presence_info
|
|
31
|
+
# nothing
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -1,27 +1,4 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
require_relative "rubocop/cops/anycable/stream_from"
|
|
7
|
-
require_relative "rubocop/cops/anycable/periodical_timers"
|
|
8
|
-
require_relative "rubocop/cops/anycable/instance_vars"
|
|
9
|
-
|
|
10
|
-
module RuboCop
|
|
11
|
-
module AnyCable # :nodoc:
|
|
12
|
-
CONFIG_DEFAULT = Pathname.new(__dir__).join("rubocop", "config", "default.yml").freeze
|
|
13
|
-
|
|
14
|
-
# Merge anycable config into default configuration
|
|
15
|
-
# See https://github.com/backus/rubocop-rspec/blob/master/lib/rubocop/rspec/inject.rb
|
|
16
|
-
def self.inject!
|
|
17
|
-
path = CONFIG_DEFAULT.to_s
|
|
18
|
-
puts "configuration from #{path}" if ConfigLoader.debug?
|
|
19
|
-
hash = ConfigLoader.send(:load_yaml_configuration, path)
|
|
20
|
-
config = Config.new(hash, path)
|
|
21
|
-
config = ConfigLoader.merge_with_default(config, path)
|
|
22
|
-
ConfigLoader.instance_variable_set(:@default_configuration, config)
|
|
23
|
-
end
|
|
24
|
-
end
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
RuboCop::AnyCable.inject!
|
|
3
|
+
# For backwards compatibility
|
|
4
|
+
require_relative "../rubocop"
|
|
@@ -9,6 +9,7 @@ require "anyway/rails"
|
|
|
9
9
|
# - `access_logs_disabled` (defaults to true) — whether to print Started/Finished logs
|
|
10
10
|
# - `persistent_session_enabled` (defaults to false) — whether to store session changes in the connection state
|
|
11
11
|
# - `embedded` (defaults to false) — whether to run RPC server inside a Rails server process
|
|
12
|
+
# - `http_rpc` (default to false) - whether to mount HTTP RPC server or not
|
|
12
13
|
# - `http_rpc_mount_path` (defaults to nil) — path to mount HTTP RPC server
|
|
13
14
|
# - `batch_broadcasts` (defaults to false) — whether to batch broadcasts automatically for code wrapped with Rails executor
|
|
14
15
|
# - `jwt_param` (defaults to 'jid') — the name of the JWT authentication query paramter or header
|
|
@@ -18,6 +19,7 @@ AnyCable::Config.attr_config(
|
|
|
18
19
|
persistent_session_enabled: false,
|
|
19
20
|
embedded: false,
|
|
20
21
|
jwt_param: "jid",
|
|
22
|
+
http_rpc: false,
|
|
21
23
|
http_rpc_mount_path: nil,
|
|
22
24
|
batch_broadcasts: false,
|
|
23
25
|
socket_id_header: "X-Socket-ID",
|
|
@@ -31,15 +31,69 @@ 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"])
|
|
48
|
+
|
|
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"]
|
|
58
|
+
end
|
|
37
59
|
|
|
38
|
-
|
|
39
|
-
|
|
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]
|
|
40
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]
|
|
41
74
|
|
|
42
|
-
|
|
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
|
+
if id_options[:channel] == "$pubsub"
|
|
84
|
+
PubSubChannel
|
|
85
|
+
else
|
|
86
|
+
id_options[:channel].safe_constantize
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def subscription_from_identifier(id_key)
|
|
91
|
+
subscription_klass = subscription_class_from_identifier(id_key)
|
|
92
|
+
|
|
93
|
+
if subscription_klass && subscription_klass < ActionCable::Channel::Base
|
|
94
|
+
id_options = ActiveSupport::JSON.decode(id_key).with_indifferent_access
|
|
95
|
+
subscription_klass.new(connection, id_key, id_options)
|
|
96
|
+
end
|
|
43
97
|
end
|
|
44
98
|
end
|
|
45
99
|
end)
|
|
@@ -74,15 +128,8 @@ module AnyCable
|
|
|
74
128
|
conn.cached_ids = {}
|
|
75
129
|
conn.anycable_request_builder = self
|
|
76
130
|
|
|
77
|
-
return unless subscriptions
|
|
78
|
-
|
|
79
131
|
# 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
|
|
132
|
+
conn.subscriptions.restore(subscriptions, socket.istate) if subscriptions
|
|
86
133
|
end
|
|
87
134
|
|
|
88
135
|
def handle_open
|
|
@@ -111,26 +158,8 @@ module AnyCable
|
|
|
111
158
|
|
|
112
159
|
def handle_channel_command(identifier, command, data)
|
|
113
160
|
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
|
|
161
|
+
conn.subscriptions.execute_rpc_command({"command" => command, "identifier" => identifier, "data" => data})
|
|
131
162
|
end
|
|
132
|
-
# Support rescue_from
|
|
133
|
-
# https://github.com/rails/rails/commit/d2571e560c62116f60429c933d0c41a0e249b58b
|
|
134
163
|
rescue Exception => e # rubocop:disable Lint/RescueException
|
|
135
164
|
rescue_with_handler(e) || raise
|
|
136
165
|
false
|
|
@@ -6,6 +6,20 @@ module AnyCable
|
|
|
6
6
|
module SerializableIdentification
|
|
7
7
|
extend ActiveSupport::Concern
|
|
8
8
|
|
|
9
|
+
module ConnectionGID
|
|
10
|
+
def connection_identifier
|
|
11
|
+
unless defined? @connection_identifier
|
|
12
|
+
@connection_identifier = connection_gid identifiers.filter_map { |id| instance_variable_get(:"@#{id}") || __send__(id) }
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
@connection_identifier
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
included do
|
|
20
|
+
prepend ConnectionGID
|
|
21
|
+
end
|
|
22
|
+
|
|
9
23
|
class_methods do
|
|
10
24
|
def identified_by(*identifiers)
|
|
11
25
|
super
|
|
@@ -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)
|
|
@@ -113,6 +113,7 @@ module AnyCable
|
|
|
113
113
|
initializer "anycable.routes" do
|
|
114
114
|
config.after_initialize do |app|
|
|
115
115
|
config = AnyCable.config
|
|
116
|
+
config.http_rpc_mount_path ||= "/_anycable" if config.http_rpc?
|
|
116
117
|
unless config.http_rpc_mount_path.nil?
|
|
117
118
|
app.routes.prepend do
|
|
118
119
|
mount AnyCable::HTTRPC::Server.new => config.http_rpc_mount_path, :internal => true
|
|
@@ -123,11 +124,12 @@ module AnyCable
|
|
|
123
124
|
|
|
124
125
|
initializer "anycable.verify_pool_sizes" do
|
|
125
126
|
next if AnyCable.config.disable_rpc_pool_size_warning?
|
|
126
|
-
# Skip if non-gRPC server is used
|
|
127
|
-
next unless AnyCable.config.respond_to?(:rpc_pool_size)
|
|
128
127
|
|
|
129
128
|
# Log current db vs. gRPC pool sizes
|
|
130
129
|
AnyCable.configure_server do
|
|
130
|
+
# Skip if non-gRPC server is used
|
|
131
|
+
next unless AnyCable.config.respond_to?(:rpc_pool_size)
|
|
132
|
+
|
|
131
133
|
ActiveSupport.on_load(:active_record) do
|
|
132
134
|
db_pool_size = ::ActiveRecord::Base.connection_pool.size
|
|
133
135
|
rpc_pool_size = AnyCable.config.rpc_pool_size
|
data/lib/anycable/rails/{compatibility/rubocop → rubocop}/cops/anycable/periodical_timers.rb
RENAMED
|
@@ -13,16 +13,11 @@ module RuboCop
|
|
|
13
13
|
# periodically(:do_something, every: 2.seconds)
|
|
14
14
|
# end
|
|
15
15
|
#
|
|
16
|
-
class PeriodicalTimers < RuboCop::Cop::
|
|
16
|
+
class PeriodicalTimers < RuboCop::Cop::Base
|
|
17
17
|
MSG = "Periodical Timers are not supported in AnyCable"
|
|
18
|
+
RESTRICT_ON_SEND = %i[periodically].freeze
|
|
18
19
|
|
|
19
|
-
|
|
20
|
-
(send _ :periodically ...)
|
|
21
|
-
PATTERN
|
|
22
|
-
|
|
23
|
-
def on_send(node)
|
|
24
|
-
add_offense(node) if calls_periodically?(node)
|
|
25
|
-
end
|
|
20
|
+
alias_method :on_send, :add_offense
|
|
26
21
|
end
|
|
27
22
|
end
|
|
28
23
|
end
|
|
@@ -34,7 +34,7 @@ module RuboCop
|
|
|
34
34
|
# end
|
|
35
35
|
# end
|
|
36
36
|
#
|
|
37
|
-
class StreamFrom < RuboCop::Cop::
|
|
37
|
+
class StreamFrom < RuboCop::Cop::Base
|
|
38
38
|
def_node_matcher :stream_from_with_block?, <<-PATTERN
|
|
39
39
|
(block {(send _ :stream_from ...) (send _ :stream_for ...)} ...)
|
|
40
40
|
PATTERN
|
|
@@ -81,16 +81,14 @@ module RuboCop
|
|
|
81
81
|
|
|
82
82
|
def add_callback_offense(node)
|
|
83
83
|
add_offense(
|
|
84
|
-
node,
|
|
85
|
-
location: :expression,
|
|
84
|
+
node.loc.expression,
|
|
86
85
|
message: "Custom stream callbacks are not supported in AnyCable"
|
|
87
86
|
)
|
|
88
87
|
end
|
|
89
88
|
|
|
90
89
|
def add_custom_coder_offense(node)
|
|
91
90
|
add_offense(
|
|
92
|
-
node,
|
|
93
|
-
location: :expression,
|
|
91
|
+
node.loc.expression,
|
|
94
92
|
message: "Custom coders are not supported in AnyCable"
|
|
95
93
|
)
|
|
96
94
|
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "rubocop"
|
|
4
|
+
require "pathname"
|
|
5
|
+
|
|
6
|
+
require_relative "rubocop/cops/anycable/stream_from"
|
|
7
|
+
require_relative "rubocop/cops/anycable/periodical_timers"
|
|
8
|
+
require_relative "rubocop/cops/anycable/instance_vars"
|
|
9
|
+
|
|
10
|
+
module RuboCop
|
|
11
|
+
module AnyCable # :nodoc:
|
|
12
|
+
CONFIG_DEFAULT = Pathname.new(__dir__).join("rubocop", "config", "default.yml").freeze
|
|
13
|
+
|
|
14
|
+
# Merge anycable config into default configuration
|
|
15
|
+
# See https://github.com/backus/rubocop-rspec/blob/master/lib/rubocop/rspec/inject.rb
|
|
16
|
+
def self.inject!
|
|
17
|
+
path = CONFIG_DEFAULT.to_s
|
|
18
|
+
puts "configuration from #{path}" if ConfigLoader.debug?
|
|
19
|
+
hash = ConfigLoader.send(:load_yaml_configuration, path)
|
|
20
|
+
config = Config.new(hash, path)
|
|
21
|
+
config = ConfigLoader.merge_with_default(config, path)
|
|
22
|
+
ConfigLoader.instance_variable_set(:@default_configuration, config)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
RuboCop::AnyCable.inject!
|
|
@@ -11,8 +11,8 @@ module AnyCable
|
|
|
11
11
|
|
|
12
12
|
private
|
|
13
13
|
|
|
14
|
-
def anycable_tracking_socket_id(&)
|
|
15
|
-
Rails.with_socket_id(request.headers[AnyCable.config.socket_id_header], &)
|
|
14
|
+
def anycable_tracking_socket_id(&block)
|
|
15
|
+
Rails.with_socket_id(request.headers[AnyCable.config.socket_id_header], &block)
|
|
16
16
|
end
|
|
17
17
|
end
|
|
18
18
|
|
data/lib/anycable/rails.rb
CHANGED
|
@@ -9,6 +9,7 @@ require "globalid"
|
|
|
9
9
|
require "active_support/core_ext/module/attribute_accessors_per_thread"
|
|
10
10
|
|
|
11
11
|
require "anycable/rails/ext"
|
|
12
|
+
require "anycable/rails/channel"
|
|
12
13
|
|
|
13
14
|
module AnyCable
|
|
14
15
|
# Rails handler for AnyCable
|
|
@@ -84,7 +85,7 @@ end
|
|
|
84
85
|
|
|
85
86
|
# Warn if application has been already initialized.
|
|
86
87
|
# AnyCable should be loaded before initialization in order to work correctly.
|
|
87
|
-
if defined?(::Rails) && ::Rails.application
|
|
88
|
+
if defined?(::Rails) && ::Rails.application&.initialized?
|
|
88
89
|
puts("\n**************************************************")
|
|
89
90
|
puts(
|
|
90
91
|
"⛔️ WARNING: AnyCable loaded after application initialization. Might not work correctly.\n" \
|
|
@@ -10,6 +10,11 @@ if [ ! -f ./bin/dist/anycable-go ]; then
|
|
|
10
10
|
./bin/rails g anycable:download --version=$version --bin-path=./bin/dist
|
|
11
11
|
fi
|
|
12
12
|
|
|
13
|
+
if [ -x ./bin/dist/anycable-go ]; then
|
|
14
|
+
echo "Setting execution permission for AnyCable server"
|
|
15
|
+
chmod +x ./bin/dist/anycable-go
|
|
16
|
+
fi
|
|
17
|
+
|
|
13
18
|
curVersion=$(./bin/dist/anycable-go -v)
|
|
14
19
|
|
|
15
20
|
if [[ "$version" != "latest" ]]; then
|
|
@@ -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
|
|