anycable-rails 1.0.0.preview2 → 1.0.0.rc1
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 +14 -125
- data/README.md +14 -34
- data/lib/anycable/rails.rb +36 -2
- data/lib/anycable/rails/actioncable/channel.rb +4 -0
- data/lib/anycable/rails/actioncable/connection.rb +24 -35
- data/lib/anycable/rails/actioncable/connection/serializable_identification.rb +42 -0
- data/lib/anycable/rails/actioncable/remote_connections.rb +11 -0
- data/lib/anycable/rails/channel_state.rb +48 -0
- data/lib/anycable/rails/compatibility.rb +4 -7
- data/lib/anycable/rails/compatibility/rubocop.rb +0 -1
- data/lib/anycable/rails/compatibility/rubocop/config/default.yml +3 -0
- data/lib/anycable/rails/compatibility/rubocop/cops/anycable/instance_vars.rb +1 -1
- data/lib/anycable/rails/compatibility/rubocop/cops/anycable/stream_from.rb +4 -4
- data/lib/anycable/rails/railtie.rb +10 -10
- data/lib/anycable/rails/refinements/subscriptions.rb +5 -0
- data/lib/anycable/rails/session_proxy.rb +19 -2
- data/lib/anycable/rails/version.rb +1 -1
- data/lib/generators/anycable/download/USAGE +14 -0
- data/lib/generators/anycable/download/download_generator.rb +77 -0
- data/lib/generators/anycable/setup/USAGE +2 -0
- data/lib/{rails/generators → generators}/anycable/setup/setup_generator.rb +67 -89
- data/lib/{rails/generators → generators}/anycable/setup/templates/Procfile.dev +0 -0
- data/lib/{rails/generators → generators}/anycable/setup/templates/config/anycable.yml.tt +12 -1
- data/lib/generators/anycable/setup/templates/config/cable.yml.tt +11 -0
- data/lib/{rails/generators/anycable/setup/templates/config/initializers/anycable.rb → generators/anycable/setup/templates/config/initializers/anycable.rb.tt} +1 -1
- data/lib/generators/anycable/with_os_helpers.rb +55 -0
- metadata +23 -47
- data/lib/anycable/rails/compatibility/rubocop/cops/anycable/remote_disconnect.rb +0 -31
- data/lib/rails/generators/anycable/setup/templates/Procfile +0 -2
- data/lib/rails/generators/anycable/setup/templates/bin/heroku-web +0 -7
- data/lib/rails/generators/anycable/setup/templates/config/cable.yml.tt +0 -11
@@ -0,0 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "action_cable/remote_connections"
|
4
|
+
|
5
|
+
ActionCable::RemoteConnections::RemoteConnection.include(ActionCable::Connection::SerializableIdentification)
|
6
|
+
|
7
|
+
ActionCable::RemoteConnections::RemoteConnection.prepend(Module.new do
|
8
|
+
def disconnect(reconnect: true)
|
9
|
+
::AnyCable.broadcast_adapter.broadcast_command("disconnect", identifier: identifiers_json, reconnect: reconnect)
|
10
|
+
end
|
11
|
+
end)
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module AnyCable
|
4
|
+
module Rails
|
5
|
+
module ChannelState
|
6
|
+
module ClassMethods
|
7
|
+
def state_attr_accessor(*names)
|
8
|
+
return attr_accessor(*names) unless AnyCable::Rails.enabled?
|
9
|
+
|
10
|
+
names.each do |name|
|
11
|
+
channel_state_attributes << name
|
12
|
+
class_eval <<~RUBY, __FILE__, __LINE__ + 1
|
13
|
+
def #{name}
|
14
|
+
return @#{name} if instance_variable_defined?(:@#{name})
|
15
|
+
@#{name} = AnyCable::Rails.deserialize(connection.socket.istate["#{name}"], json: true)
|
16
|
+
end
|
17
|
+
|
18
|
+
def #{name}=(val)
|
19
|
+
connection.socket.istate["#{name}"] = AnyCable::Rails.serialize(val, json: true)
|
20
|
+
instance_variable_set(:@#{name}, val)
|
21
|
+
end
|
22
|
+
RUBY
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def channel_state_attributes
|
27
|
+
return @channel_state_attributes if instance_variable_defined?(:@channel_state_attributes)
|
28
|
+
|
29
|
+
@channel_state_attributes =
|
30
|
+
if superclass.respond_to?(:channel_state_attributes)
|
31
|
+
superclass.channel_state_attributes.dup
|
32
|
+
else
|
33
|
+
[]
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.included(base)
|
39
|
+
base.extend ClassMethods
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
ActiveSupport.on_load(:action_cable) do
|
46
|
+
# `state_attr_accessor` must be available in Action Cable
|
47
|
+
::ActionCable::Channel::Base.include(AnyCable::Rails::ChannelState)
|
48
|
+
end
|
@@ -33,6 +33,10 @@ module AnyCable
|
|
33
33
|
res = yield
|
34
34
|
diff = instance_variables - was_ivars
|
35
35
|
|
36
|
+
if self.class.respond_to?(:channel_state_attributes)
|
37
|
+
diff.delete_if { |ivar| self.class.channel_state_attributes.include?(:"#{ivar.to_s.sub(/^@/, "")}") }
|
38
|
+
end
|
39
|
+
|
36
40
|
unless diff.empty?
|
37
41
|
raise AnyCable::CompatibilityError,
|
38
42
|
"Channel instance variables are not supported by AnyCable, " \
|
@@ -48,12 +52,5 @@ module AnyCable
|
|
48
52
|
raise AnyCable::CompatibilityError, "Periodical timers are not supported by AnyCable"
|
49
53
|
end
|
50
54
|
end)
|
51
|
-
|
52
|
-
ActionCable::RemoteConnections::RemoteConnection.prepend(Module.new do
|
53
|
-
def disconnect
|
54
|
-
raise AnyCable::CompatibilityError,
|
55
|
-
"Disconnecting remote clients is not supported by AnyCable yet"
|
56
|
-
end
|
57
|
-
end)
|
58
55
|
end
|
59
56
|
end
|
@@ -4,7 +4,6 @@ require "rubocop"
|
|
4
4
|
require "pathname"
|
5
5
|
|
6
6
|
require_relative "rubocop/cops/anycable/stream_from"
|
7
|
-
require_relative "rubocop/cops/anycable/remote_disconnect"
|
8
7
|
require_relative "rubocop/cops/anycable/periodical_timers"
|
9
8
|
require_relative "rubocop/cops/anycable/instance_vars"
|
10
9
|
|
@@ -25,7 +25,7 @@ module RuboCop
|
|
25
25
|
# end
|
26
26
|
#
|
27
27
|
class InstanceVars < RuboCop::Cop::Cop
|
28
|
-
MSG = "Channel instance variables are not supported in AnyCable"
|
28
|
+
MSG = "Channel instance variables are not supported in AnyCable. Use `state_attr_accessor` instead"
|
29
29
|
|
30
30
|
def on_class(node)
|
31
31
|
find_nested_ivars(node) do |nested_ivar|
|
@@ -11,7 +11,7 @@ module RuboCop
|
|
11
11
|
# # bad
|
12
12
|
# class MyChannel < ApplicationCable::Channel
|
13
13
|
# def follow
|
14
|
-
#
|
14
|
+
# stream_for(room) {}
|
15
15
|
# end
|
16
16
|
# end
|
17
17
|
#
|
@@ -36,15 +36,15 @@ module RuboCop
|
|
36
36
|
#
|
37
37
|
class StreamFrom < RuboCop::Cop::Cop
|
38
38
|
def_node_matcher :stream_from_with_block?, <<-PATTERN
|
39
|
-
(block (send _ :stream_from ...) ...)
|
39
|
+
(block {(send _ :stream_from ...) (send _ :stream_for ...)} ...)
|
40
40
|
PATTERN
|
41
41
|
|
42
42
|
def_node_matcher :stream_from_with_callback?, <<-PATTERN
|
43
|
-
(send _ :stream_from str_type? (block (send nil? :lambda) ...))
|
43
|
+
{(send _ :stream_from str_type? (block (send nil? :lambda) ...)) (send _ :stream_for ... (block (send nil? :lambda) ...))}
|
44
44
|
PATTERN
|
45
45
|
|
46
46
|
def_node_matcher :args_of_stream_from, <<-PATTERN
|
47
|
-
(send _ :stream_from str_type? $...)
|
47
|
+
{(send _ :stream_from str_type? $...) (send _ :stream_for $...)}
|
48
48
|
PATTERN
|
49
49
|
|
50
50
|
def_node_matcher :coder_symbol?, "(pair (sym :coder) ...)"
|
@@ -1,23 +1,24 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "anycable/rails/channel_state"
|
4
|
+
|
3
5
|
module AnyCable
|
4
6
|
module Rails
|
5
7
|
class Railtie < ::Rails::Railtie # :nodoc:
|
6
8
|
initializer "anycable.disable_action_cable_mount", after: "action_cable.set_configs" do |app|
|
7
|
-
|
8
|
-
adapter = ::ActionCable.server.config.cable&.fetch("adapter", nil)
|
9
|
-
next unless AnyCable::Rails.compatible_adapter?(adapter)
|
9
|
+
next unless AnyCable::Rails.enabled?
|
10
10
|
|
11
11
|
app.config.action_cable.mount_path = nil
|
12
12
|
end
|
13
13
|
|
14
14
|
initializer "anycable.logger", after: "action_cable.logger" do |_app|
|
15
|
-
AnyCable.logger =
|
15
|
+
AnyCable.logger = ::ActionCable.server.config.logger
|
16
16
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
17
|
+
AnyCable.configure_server do
|
18
|
+
AnyCable.logger = ActiveSupport::TaggedLogging.new(::ActionCable.server.config.logger)
|
19
|
+
# Broadcast server logs to STDOUT in development
|
20
|
+
if ::Rails.env.development? &&
|
21
|
+
!ActiveSupport::Logger.logger_outputs_to?(::Rails.logger, STDOUT)
|
21
22
|
console = ActiveSupport::Logger.new(STDOUT)
|
22
23
|
console.formatter = ::Rails.logger.formatter
|
23
24
|
console.level = ::Rails.logger.level
|
@@ -42,8 +43,7 @@ module AnyCable
|
|
42
43
|
|
43
44
|
initializer "anycable.connection_factory", after: "action_cable.set_configs" do |app|
|
44
45
|
ActiveSupport.on_load(:action_cable) do
|
45
|
-
|
46
|
-
if AnyCable::Rails.compatible_adapter?(adapter)
|
46
|
+
if AnyCable::Rails.enabled?
|
47
47
|
require "anycable/rails/actioncable/connection"
|
48
48
|
|
49
49
|
if AnyCable.config.persistent_session_enabled
|
@@ -7,6 +7,11 @@ module AnyCable
|
|
7
7
|
# Find or add a subscription to the list
|
8
8
|
def fetch(identifier)
|
9
9
|
add("identifier" => identifier) unless subscriptions[identifier]
|
10
|
+
|
11
|
+
unless subscriptions[identifier]
|
12
|
+
raise "Channel not found: #{ActiveSupport::JSON.decode(identifier).fetch("channel")}"
|
13
|
+
end
|
14
|
+
|
10
15
|
subscriptions[identifier]
|
11
16
|
end
|
12
17
|
end
|
@@ -5,8 +5,6 @@ module AnyCable
|
|
5
5
|
# Wrap `request.session` to lazily load values provided
|
6
6
|
# in the RPC call (set by the previous calls)
|
7
7
|
class SessionProxy
|
8
|
-
delegate_missing_to :@rack_session
|
9
|
-
|
10
8
|
attr_reader :rack_session, :socket_session
|
11
9
|
|
12
10
|
def initialize(rack_session, socket_session)
|
@@ -41,6 +39,25 @@ module AnyCable
|
|
41
39
|
rack_session.keys + socket_session.keys
|
42
40
|
end
|
43
41
|
|
42
|
+
# Delegate both publuc and private methods to rack_session
|
43
|
+
def respond_to_missing?(name, include_private = false)
|
44
|
+
return false if name == :marshal_dump || name == :_dump
|
45
|
+
rack_session.respond_to?(name, include_private) || super
|
46
|
+
end
|
47
|
+
|
48
|
+
def method_missing(method, *args, &block)
|
49
|
+
if rack_session.respond_to?(method, true)
|
50
|
+
rack_session.send(method, *args, &block)
|
51
|
+
else
|
52
|
+
super
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# This method is used by StimulusReflex to obtain `@by`
|
57
|
+
def instance_variable_get(name)
|
58
|
+
super || rack_session.instance_variable_get(name)
|
59
|
+
end
|
60
|
+
|
44
61
|
private
|
45
62
|
|
46
63
|
def restore!
|
@@ -0,0 +1,14 @@
|
|
1
|
+
Description:
|
2
|
+
Install AnyCable-Go web server.
|
3
|
+
|
4
|
+
Example:
|
5
|
+
rails generate anycable:download
|
6
|
+
|
7
|
+
This will ask:
|
8
|
+
Where to store a binary file.
|
9
|
+
This will create:
|
10
|
+
`<bin_path>/anycable-go`.
|
11
|
+
|
12
|
+
rails generate anycable:download --bin-path=/usr/local/bin
|
13
|
+
|
14
|
+
rails generate anycable:download --version=1.0.0
|
@@ -0,0 +1,77 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "generators/anycable/with_os_helpers"
|
4
|
+
|
5
|
+
module AnyCableRailsGenerators
|
6
|
+
# Downloads anycable-go binary
|
7
|
+
class DownloadGenerator < ::Rails::Generators::Base
|
8
|
+
namespace "anycable:download"
|
9
|
+
|
10
|
+
include WithOSHelpers
|
11
|
+
|
12
|
+
# TODO: change to latest release
|
13
|
+
VERSION = "1.0.0.preview1"
|
14
|
+
|
15
|
+
class_option :bin_path,
|
16
|
+
type: :string,
|
17
|
+
desc: "Where to download AnyCable-Go server binary (default: #{DEFAULT_BIN_PATH})"
|
18
|
+
class_option :version,
|
19
|
+
type: :string,
|
20
|
+
desc: "Specify the AnyCable-Go version (defaults to latest release)"
|
21
|
+
|
22
|
+
def download_bin
|
23
|
+
out = options[:bin_path] || DEFAULT_BIN_PATH
|
24
|
+
version = options[:version] || VERSION
|
25
|
+
|
26
|
+
download_exe(
|
27
|
+
release_url(version),
|
28
|
+
to: out,
|
29
|
+
file_name: "anycable-go"
|
30
|
+
)
|
31
|
+
|
32
|
+
true
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def release_url(version)
|
38
|
+
if Gem::Version.new(version).segments.first >= 1
|
39
|
+
new_release_url(version)
|
40
|
+
else
|
41
|
+
legacy_release_url(version)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def legacy_release_url(version)
|
46
|
+
"https://github.com/anycable/anycable-go/releases/download/v#{version}/" \
|
47
|
+
"anycable-go-v#{version}-#{os_name}-#{cpu_name}"
|
48
|
+
end
|
49
|
+
|
50
|
+
def new_release_url(version)
|
51
|
+
"https://github.com/anycable/anycable-go/releases/download/v#{version}/" \
|
52
|
+
"anycable-go-#{os_name}-#{cpu_name}"
|
53
|
+
end
|
54
|
+
|
55
|
+
def download_exe(url, to:, file_name:)
|
56
|
+
file_path = File.join(to, file_name)
|
57
|
+
|
58
|
+
run "#{sudo(to)}curl -L #{url} -o #{file_path}", abort_on_failure: true
|
59
|
+
run "#{sudo(to)}chmod +x #{file_path}", abort_on_failure: true
|
60
|
+
run "#{file_path} -v", abort_on_failure: true
|
61
|
+
end
|
62
|
+
|
63
|
+
def sudo(path)
|
64
|
+
sudo = ""
|
65
|
+
unless File.writable?(path)
|
66
|
+
if yes? "Path is not writable 😕. Do you have sudo privileges?"
|
67
|
+
sudo = "sudo "
|
68
|
+
else
|
69
|
+
say_status :error, "❌ Failed to install AnyCable-Go WebSocket server", :red
|
70
|
+
raise StandardError, "Path #{path} is not writable!"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
sudo
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -1,34 +1,23 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "generators/anycable/with_os_helpers"
|
4
|
+
|
3
5
|
module AnyCableRailsGenerators
|
4
6
|
# Entry point for interactive installation
|
5
7
|
class SetupGenerator < ::Rails::Generators::Base
|
6
8
|
namespace "anycable:setup"
|
7
9
|
source_root File.expand_path("templates", __dir__)
|
8
10
|
|
9
|
-
|
10
|
-
|
11
|
-
SERVER_VERSION = "v1.0.0.preview1"
|
12
|
-
OS_NAMES = %w[linux darwin freebsd win].freeze
|
13
|
-
CPU_NAMES = %w[amd64 arm64 386 arm].freeze
|
11
|
+
DOCS_ROOT = "https://docs.anycable.io/v1/#"
|
12
|
+
DEVELOPMENT_METHODS = %w[skip local docker].freeze
|
14
13
|
SERVER_SOURCES = %w[skip brew binary].freeze
|
15
|
-
DEFAULT_BIN_PATH = "/usr/local/bin"
|
16
14
|
|
17
|
-
class_option :
|
15
|
+
class_option :devenv,
|
18
16
|
type: :string,
|
19
|
-
desc: "Select your development environment (options: #{
|
17
|
+
desc: "Select your development environment (options: #{DEVELOPMENT_METHODS.join(", ")})"
|
20
18
|
class_option :source,
|
21
19
|
type: :string,
|
22
20
|
desc: "Choose a way of installing AnyCable-Go server (options: #{SERVER_SOURCES.join(", ")})"
|
23
|
-
class_option :bin_path,
|
24
|
-
type: :string,
|
25
|
-
desc: "Where to download AnyCable-Go server binary (default: #{DEFAULT_BIN_PATH})"
|
26
|
-
class_option :os,
|
27
|
-
type: :string,
|
28
|
-
desc: "Specify the OS for AnyCable-Go server binary (options: #{OS_NAMES.join(", ")})"
|
29
|
-
class_option :cpu,
|
30
|
-
type: :string,
|
31
|
-
desc: "Specify the CPU architecturefor AnyCable-Go server binary (options: #{CPU_NAMES.join(", ")})"
|
32
21
|
class_option :skip_heroku,
|
33
22
|
type: :boolean,
|
34
23
|
desc: "Do not copy Heroku configs"
|
@@ -36,6 +25,15 @@ module AnyCableRailsGenerators
|
|
36
25
|
type: :boolean,
|
37
26
|
desc: "Do not create Procfile.dev"
|
38
27
|
|
28
|
+
include WithOSHelpers
|
29
|
+
|
30
|
+
class_option :bin_path,
|
31
|
+
type: :string,
|
32
|
+
desc: "Where to download AnyCable-Go server binary (default: #{DEFAULT_BIN_PATH})"
|
33
|
+
class_option :version,
|
34
|
+
type: :string,
|
35
|
+
desc: "Specify the AnyCable-Go version (defaults to latest release)"
|
36
|
+
|
39
37
|
def welcome
|
40
38
|
say "👋 Welcome to AnyCable interactive installer."
|
41
39
|
end
|
@@ -51,32 +49,32 @@ module AnyCableRailsGenerators
|
|
51
49
|
environment(nil, env: :development) do
|
52
50
|
<<~SNIPPET
|
53
51
|
# Specify AnyCable WebSocket server URL to use by JS client
|
54
|
-
config.action_cable.url = ENV.fetch("CABLE_URL", "ws://localhost:
|
52
|
+
config.action_cable.url = ENV.fetch("CABLE_URL", "ws://localhost:8080/cable") if AnyCable::Rails.enabled?
|
55
53
|
SNIPPET
|
56
54
|
end
|
57
55
|
|
58
56
|
environment(nil, env: :production) do
|
59
57
|
<<~SNIPPET
|
60
58
|
# Specify AnyCable WebSocket server URL to use by JS client
|
61
|
-
config.action_cable.url = ENV
|
59
|
+
config.action_cable.url = ENV.fetch("CABLE_URL") if AnyCable::Rails.enabled?
|
62
60
|
SNIPPET
|
63
61
|
end
|
64
62
|
|
65
63
|
say_status :info, "✅ 'config.action_cable.url' has been configured"
|
66
|
-
say_status :help, "⚠️
|
64
|
+
say_status :help, "⚠️ If you're using JS client make sure you have " \
|
67
65
|
"`action_cable_meta_tag` included before any <script> tag in your application.html"
|
68
66
|
end
|
69
67
|
|
70
68
|
def development_method
|
71
|
-
answer =
|
69
|
+
answer = DEVELOPMENT_METHODS.index(options[:devenv]) || 99
|
72
70
|
|
73
|
-
until
|
71
|
+
until DEVELOPMENT_METHODS[answer.to_i]
|
74
72
|
answer = ask "Which environment do you use for development? (1) Local, (2) Docker, (0) Skip"
|
75
73
|
end
|
76
74
|
|
77
|
-
case env =
|
75
|
+
case env = DEVELOPMENT_METHODS[answer.to_i]
|
78
76
|
when "skip"
|
79
|
-
say_status :help, "⚠️
|
77
|
+
say_status :help, "⚠️ Please, read this guide on how to install AnyCable-Go server 👉 #{DOCS_ROOT}/anycable-go/getting_started", :yellow
|
80
78
|
else
|
81
79
|
send "install_for_#{env}"
|
82
80
|
end
|
@@ -84,15 +82,21 @@ module AnyCableRailsGenerators
|
|
84
82
|
|
85
83
|
def heroku
|
86
84
|
if options[:skip_heroku].nil?
|
87
|
-
return unless yes? "Do you use Heroku for deployment?"
|
85
|
+
return unless yes? "Do you use Heroku for deployment? [Yn]"
|
88
86
|
elsif options[:skip_heroku]
|
89
87
|
return
|
90
88
|
end
|
91
89
|
|
92
|
-
|
93
|
-
|
90
|
+
in_root do
|
91
|
+
next unless File.file?("Procfile")
|
92
|
+
|
93
|
+
contents = File.read("Procfile")
|
94
|
+
contents.sub!(/^web: (.*)$/, %q(web: [[ "$ANYCABLE_DEPLOYMENT" == "true" ]] && bundle exec anycable --server-command="anycable-go" || \1))
|
95
|
+
File.write("Procfile", contents)
|
96
|
+
say_status :info, "✅ Procfile updated"
|
97
|
+
end
|
94
98
|
|
95
|
-
say_status :help, "️️⚠️
|
99
|
+
say_status :help, "️️⚠️ Please, read the required steps to configure Heroku applications 👉 #{DOCS_ROOT}/deployment/heroku", :yellow
|
96
100
|
end
|
97
101
|
|
98
102
|
def devise
|
@@ -107,6 +111,14 @@ module AnyCableRailsGenerators
|
|
107
111
|
say_status :info, "✅ config/initializers/anycable.rb with Devise configuration has been added"
|
108
112
|
end
|
109
113
|
|
114
|
+
def rubocop_compatibility
|
115
|
+
return unless rubocop?
|
116
|
+
|
117
|
+
say_status :info, "🤖 Running static compatibility checks with RuboCop"
|
118
|
+
res = run "bundle exec rubocop -r 'anycable/rails/compatibility/rubocop' --only AnyCable/InstanceVars,AnyCable/PeriodicalTimers,AnyCable/InstanceVars"
|
119
|
+
say_status :help, "⚠️ Please, take a look at the icompatibilities above and fix them. See https://docs.anycable.io/v1/#/ruby/compatibility" unless res
|
120
|
+
end
|
121
|
+
|
110
122
|
def finish
|
111
123
|
say_status :info, "✅ AnyCable has been configured successfully!"
|
112
124
|
end
|
@@ -114,7 +126,15 @@ module AnyCableRailsGenerators
|
|
114
126
|
private
|
115
127
|
|
116
128
|
def stimulus_reflex?
|
117
|
-
|
129
|
+
!!gemfile_lock&.match?(/^\s+stimulus_reflex\b/)
|
130
|
+
end
|
131
|
+
|
132
|
+
def redis?
|
133
|
+
!!gemfile_lock&.match?(/^\s+redis\b/)
|
134
|
+
end
|
135
|
+
|
136
|
+
def rubocop?
|
137
|
+
!!gemfile_lock&.match?(/^\s+rubocop\b/)
|
118
138
|
end
|
119
139
|
|
120
140
|
def gemfile_lock
|
@@ -129,24 +149,23 @@ module AnyCableRailsGenerators
|
|
129
149
|
end
|
130
150
|
|
131
151
|
def install_for_docker
|
132
|
-
say_status :help, "️️⚠️
|
152
|
+
say_status :help, "️️⚠️ Docker development configuration could vary", :yellow
|
133
153
|
|
134
154
|
say "Here is an example snippet for docker-compose.yml:"
|
135
155
|
say <<~YML
|
136
156
|
─────────────────────────────────────────
|
137
|
-
|
138
|
-
image: anycable/anycable-go:
|
157
|
+
ws:
|
158
|
+
image: anycable/anycable-go:1.0.0.preview1
|
139
159
|
ports:
|
140
|
-
- '
|
160
|
+
- '8080:8080'
|
141
161
|
environment:
|
142
|
-
PORT: 3334
|
143
162
|
ANYCABLE_REDIS_URL: redis://redis:6379/0
|
144
|
-
ANYCABLE_RPC_HOST: anycable
|
163
|
+
ANYCABLE_RPC_HOST: anycable:50051
|
145
164
|
depends_on:
|
146
165
|
- anycable-rpc
|
147
166
|
- redis
|
148
167
|
|
149
|
-
anycable
|
168
|
+
anycable:
|
150
169
|
<<: *backend
|
151
170
|
command: bundle exec anycable
|
152
171
|
environment:
|
@@ -173,7 +192,7 @@ module AnyCableRailsGenerators
|
|
173
192
|
|
174
193
|
case answer.to_i
|
175
194
|
when 0
|
176
|
-
say_status :help, "⚠️
|
195
|
+
say_status :help, "⚠️ Please, read this guide on how to install AnyCable-Go server 👉 #{DOCS_ROOT}/anycable-go/getting_started", :yellow
|
177
196
|
return
|
178
197
|
else
|
179
198
|
return unless send("install_from_#{SERVER_SOURCES[answer.to_i]}")
|
@@ -206,63 +225,22 @@ module AnyCableRailsGenerators
|
|
206
225
|
end
|
207
226
|
|
208
227
|
def install_from_binary
|
209
|
-
|
210
|
-
|
211
|
-
out ||= ask "Please, enter the path to download the AnyCable-Go binary to", default: DEFAULT_BIN_PATH, path: true
|
228
|
+
bin_path ||= DEFAULT_BIN_PATH if options[:devenv] # User don't want interactive mode
|
229
|
+
bin_path ||= ask "Please, enter the path to download the AnyCable-Go binary to", default: DEFAULT_BIN_PATH, path: true
|
212
230
|
|
213
|
-
|
214
|
-
OS_NAMES.find(&Gem::Platform.local.os.method(:==)) ||
|
215
|
-
ask("What is your OS name?", limited_to: OS_NAMES)
|
216
|
-
|
217
|
-
cpu_name = options[:cpu] ||
|
218
|
-
CPU_NAMES.find(¤t_cpu.method(:==)) ||
|
219
|
-
ask("What is your CPU architecture?", limited_to: CPU_NAMES)
|
220
|
-
|
221
|
-
download_exe(
|
222
|
-
"https://github.com/anycable/anycable-go/releases/download/#{SERVER_VERSION}/" \
|
223
|
-
"anycable-go-#{os_name}-#{cpu_name}",
|
224
|
-
to: out,
|
225
|
-
file_name: "anycable-go"
|
226
|
-
)
|
231
|
+
generate "anycable:download", download_options(bin_path: bin_path)
|
227
232
|
|
228
233
|
true
|
229
234
|
end
|
230
235
|
|
231
|
-
def
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
def sudo!(path)
|
240
|
-
sudo = ""
|
241
|
-
unless File.writable?(path)
|
242
|
-
if yes? "Path is not writable 😕. Do you have sudo privileges?"
|
243
|
-
sudo = "sudo "
|
244
|
-
else
|
245
|
-
say_status :error, "❌ Failed to install AnyCable-Go WebSocket server", :red
|
246
|
-
raise StandardError, "Path #{path} is not writable!"
|
247
|
-
end
|
248
|
-
end
|
249
|
-
|
250
|
-
sudo
|
251
|
-
end
|
252
|
-
|
253
|
-
def current_cpu
|
254
|
-
case Gem::Platform.local.cpu
|
255
|
-
when "x86_64", "x64"
|
256
|
-
"amd64"
|
257
|
-
when "x86_32", "x86", "i386", "i486", "i686"
|
258
|
-
"i386"
|
259
|
-
when "aarch64", "aarch64_be", /armv8/
|
260
|
-
"arm64"
|
261
|
-
when "arm", /armv7/, /armv6/
|
262
|
-
"arm"
|
263
|
-
else
|
264
|
-
"unknown"
|
265
|
-
end
|
236
|
+
def download_options(**params)
|
237
|
+
opts = options.merge(params)
|
238
|
+
[].tap do |args|
|
239
|
+
args << "--os #{opts[:os]}" if opts[:os]
|
240
|
+
args << "--cpu #{opts[:cpu]}" if opts[:cpu]
|
241
|
+
args << "--bin-path=#{opts[:bin_path]}" if opts[:bin_path]
|
242
|
+
args << "--version #{opts[:version]}" if opts[:version]
|
243
|
+
end.join(" ")
|
266
244
|
end
|
267
245
|
end
|
268
246
|
end
|