anycable-rails-core 1.4.0 → 1.4.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7bc0b1eac8c453d0054d508826fd33e58b32684c89694fbbc393d2796db8f0c1
4
- data.tar.gz: 82ff10fabf21471a9fdcc14e6d76d294902b89372002734538b66e1e7569ab1d
3
+ metadata.gz: 713258efa713cd94cb2aa57891bf52f2483732f6e84b918a90d77924bc9d78e2
4
+ data.tar.gz: 45151b26a79c7ab05ba42629fcbb2c64a147142a39fe8d9eaff54dbce3b905c6
5
5
  SHA512:
6
- metadata.gz: 53cda30136d94edc95e319a0e80bed3ce19716d15dd0e69eae0fc14ffb0c45d58ec0fb466bece171736f4821a7aeeba6ec774c228e8915deb7b2eea01fed1565
7
- data.tar.gz: 2787f8c23179f2283fe9b68982f0e3f0ea8fde5222ef97dba7294464523d8968f57f1c71f166f0d44583047747bbd40433e7603afb07c45f3b58eac98bba3cf4
6
+ metadata.gz: d98ee91a26f73b7e9ff7c60820211ddebf53566520903f6ca26be838f4c27fed6f0a2a36787fe3207b569f32881c83efd263517eaa71a5f74bdee00dd61c63ff
7
+ data.tar.gz: e0a86e5ccbef6d7735f71663a5a9511dc9dd3a7a7df8fa1ffd4e3cccbf653184c0048cbbd22007f21614f4d78f30ee5aa4bb55b275964f1b9b690e3927c27069
data/CHANGELOG.md CHANGED
@@ -2,6 +2,24 @@
2
2
 
3
3
  ## master
4
4
 
5
+ ## 1.4.2 (2023-10-15)
6
+
7
+ - Print warning if the database pool size is less than RPC pool size. ([@palkan][])
8
+
9
+ - Add support for broadcast options (e.g., `exclude_socket`) and `broadcast ..., to_others: true`. ([@palkan][])
10
+
11
+ - Add `batch_broadcasts` option to automatically batch broadcasts for code wrapped in Rails executor. ([@palkan][])
12
+
13
+ - Fix broadcast logging in Rails 7.1. ([@iuri-gg][])
14
+
15
+ ## 1.4.1 (2023-09-27)
16
+
17
+ - Fix compatibility with Rails 7.1. ([@palkan][])
18
+
19
+ - Upgrade `anycable:setup` generator to support v1.4 features. ([@palkan][])
20
+
21
+ Add `bin/anycable-go` to use `anycable-go` locally. Add `--rpc=http` to configure for using AnyCable with HTTP RPC.
22
+
5
23
  ## 1.4.0 (2023-07-07)
6
24
 
7
25
  - Add HTTP RPC integration. ([@palkan][])
@@ -18,8 +18,11 @@ module ActionCable
18
18
  def initialize(*)
19
19
  end
20
20
 
21
- def broadcast(channel, payload)
22
- ::AnyCable.broadcast(channel, payload)
21
+ def broadcast(channel, payload, **options)
22
+ options.merge!(::AnyCable::Rails.current_broadcast_options || {})
23
+ to_others = options.delete(:to_others)
24
+ options[:exclude_socket] ||= ::AnyCable::Rails.current_socket_id if to_others
25
+ ::AnyCable.broadcast(channel, payload, **options.compact)
23
26
  end
24
27
 
25
28
  def subscribe(*)
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "action_cable"
4
+
5
+ ActionCable::Server::Base.prepend(Module.new do
6
+ def broadcast(channel, payload, **options)
7
+ return super if options.empty?
8
+
9
+ AnyCable::Rails.with_broadcast_options(**options) do
10
+ super(channel, payload)
11
+ end
12
+ end
13
+ end)
14
+
15
+ ActionCable::Channel::Base.singleton_class.prepend(Module.new do
16
+ def broadcast_to(target, payload, **options)
17
+ return super if options.empty?
18
+
19
+ AnyCable::Rails.with_broadcast_options(**options) do
20
+ super(target, payload)
21
+ end
22
+ end
23
+ end)
@@ -10,10 +10,14 @@ require "anyway/rails"
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
12
  # - `http_rpc_mount_path` (default to nil) — path to mount HTTP RPC server
13
+ # - `batch_broadcasts` (defaults to false) — whether to batch broadcasts automatically for code wrapped with Rails executor
13
14
  AnyCable::Config.attr_config(
14
15
  access_logs_disabled: true,
15
16
  persistent_session_enabled: false,
16
17
  embedded: false,
17
- http_rpc_mount_path: nil
18
+ http_rpc_mount_path: nil,
19
+ batch_broadcasts: false,
20
+ socket_id_header: "X-Socket-ID",
21
+ disable_rpc_pool_size_warning: false
18
22
  )
19
23
  AnyCable::Config.ignore_options :access_logs_disabled, :persistent_session_enabled
@@ -13,16 +13,16 @@ module AnyCable
13
13
  end
14
14
 
15
15
  def call(method, message, metadata)
16
+ sid = metadata["sid"]
17
+
16
18
  if ::Rails.respond_to?(:error)
17
19
  executor.wrap do
18
- sid = metadata["sid"]
19
-
20
20
  ::Rails.error.record(context: {method: method, payload: message.to_h, sid: sid}) do
21
- yield
21
+ Rails.with_socket_id(sid) { yield }
22
22
  end
23
23
  end
24
24
  else
25
- executor.wrap { yield }
25
+ executor.wrap { Rails.with_socket_id(sid) { yield } }
26
26
  end
27
27
  end
28
28
  end
@@ -3,6 +3,7 @@
3
3
  require "anycable/rails/action_cable_ext/connection"
4
4
  require "anycable/rails/action_cable_ext/channel"
5
5
  require "anycable/rails/action_cable_ext/remote_connections"
6
+ require "anycable/rails/action_cable_ext/broadcast_options"
6
7
 
7
8
  require "anycable/rails/channel_state"
8
9
  require "anycable/rails/connection_factory"
@@ -21,15 +22,23 @@ module AnyCable
21
22
 
22
23
  AnyCable.configure_server do
23
24
  server_logger = AnyCable.logger = ::ActionCable.server.config.logger
24
- AnyCable.logger = ActiveSupport::TaggedLogging.new(server_logger) if server_logger.is_a?(::Logger)
25
+
25
26
  # Broadcast server logs to STDOUT in development
26
27
  if ::Rails.env.development? &&
27
28
  !ActiveSupport::Logger.logger_outputs_to?(::Rails.logger, $stdout)
28
29
  console = ActiveSupport::Logger.new($stdout)
29
30
  console.formatter = ::Rails.logger.formatter if ::Rails.logger.respond_to?(:formatter)
30
31
  console.level = ::Rails.logger.level if ::Rails.logger.respond_to?(:level)
31
- AnyCable.logger.extend(ActiveSupport::Logger.broadcast(console))
32
+
33
+ # Rails 7.1+
34
+ if AnyCable.logger.respond_to?(:broadcast_to)
35
+ AnyCable.logger.broadcast_to(console)
36
+ else
37
+ AnyCable.logger.extend(ActiveSupport::Logger.broadcast(console))
38
+ end
32
39
  end
40
+
41
+ AnyCable.logger = ActiveSupport::TaggedLogging.new(AnyCable.logger) if server_logger.is_a?(::Logger)
33
42
  end
34
43
 
35
44
  # Add tagging middleware
@@ -51,6 +60,27 @@ module AnyCable
51
60
  ::Rails.error.report(ex, handled: false, context: {method: method.to_sym, payload: message})
52
61
  end
53
62
  end
63
+
64
+ if AnyCable.config.batch_broadcasts?
65
+ if AnyCable.broadcast_adapter.respond_to?(:start_batching)
66
+ app.executor.to_run { AnyCable.broadcast_adapter.start_batching }
67
+ app.executor.to_complete { AnyCable.broadcast_adapter.finish_batching }
68
+ else
69
+ warn "[AnyCable] Auto-batching is enabled for broadcasts but your anycable version doesn't support it. Please, upgrade"
70
+ end
71
+ end
72
+ end
73
+
74
+ initializer "anycable.socket_id_tracking" do
75
+ ActiveSupport.on_load(:action_controller) do
76
+ require "anycable/rails/socket_id_tracking"
77
+ include AnyCable::Rails::SocketIdTrackingController
78
+ end
79
+
80
+ ActiveSupport.on_load(:active_job) do
81
+ require "anycable/rails/socket_id_tracking"
82
+ include AnyCable::Rails::SocketIdTrackingJob
83
+ end
54
84
  end
55
85
 
56
86
  initializer "anycable.connection_factory", after: "action_cable.set_configs" do |app|
@@ -78,6 +108,27 @@ module AnyCable
78
108
  end
79
109
  end
80
110
 
111
+ initializer "anycable.verify_pool_sizes" do
112
+ next if AnyCable.config.disable_rpc_pool_size_warning?
113
+ # Skip if non-gRPC server is used
114
+ next unless AnyCable.config.respond_to?(:rpc_pool_size)
115
+
116
+ # Log current db vs. gRPC pool sizes
117
+ AnyCable.configure_server do
118
+ ActiveSupport.on_load(:active_record) do
119
+ db_pool_size = ::ActiveRecord::Base.connection_pool.size
120
+ rpc_pool_size = AnyCable.config.rpc_pool_size
121
+
122
+ if rpc_pool_size > db_pool_size
123
+ ::Kernel.warn(
124
+ "\n⛔️ WARNING: AnyCable RPC pool size (#{rpc_pool_size}) is greater than DB pool size (#{db_pool_size})\n" \
125
+ "Please, consider adjusting the database pool size to avoid connection wait times and increase throughput of your RPC server\n\n"
126
+ )
127
+ end
128
+ end
129
+ end
130
+ end
131
+
81
132
  # Since Rails 6.1
82
133
  if respond_to?(:server)
83
134
  server do
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AnyCable
4
+ module Rails
5
+ module SocketIdTrackingController
6
+ extend ActiveSupport::Concern
7
+
8
+ included do
9
+ around_action :anycable_tracking_socket_id
10
+ end
11
+
12
+ private
13
+
14
+ def anycable_tracking_socket_id(&block)
15
+ Rails.with_socket_id(request.headers[AnyCable.config.socket_id_header], &block)
16
+ end
17
+ end
18
+
19
+ module SocketIdTrackingJob
20
+ extend ActiveSupport::Concern
21
+
22
+ attr_accessor :cable_socket_id
23
+
24
+ def serialize
25
+ return super unless Rails.current_socket_id
26
+
27
+ super.merge("cable_socket_id" => Rails.current_socket_id)
28
+ end
29
+
30
+ def deserialize(job_data)
31
+ super
32
+ self.cable_socket_id = job_data["cable_socket_id"]
33
+ end
34
+
35
+ included do
36
+ around_perform do |job, block|
37
+ Rails.with_socket_id(job.cable_socket_id, &block)
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module AnyCable
4
4
  module Rails
5
- VERSION = "1.4.0"
5
+ VERSION = "1.4.2"
6
6
  end
7
7
  end
@@ -6,6 +6,7 @@ require "anycable/rails/config"
6
6
  require "anycable/rails/rack"
7
7
 
8
8
  require "globalid"
9
+ require "active_support/core_ext/module/attribute_accessors_per_thread"
9
10
 
10
11
  module AnyCable
11
12
  # Rails handler for AnyCable
@@ -14,6 +15,9 @@ module AnyCable
14
15
 
15
16
  ADAPTER_ALIASES = %w[any_cable anycable].freeze
16
17
 
18
+ thread_mattr_accessor :current_socket_id
19
+ thread_mattr_accessor :current_broadcast_options
20
+
17
21
  class << self
18
22
  def enabled?
19
23
  adapter = ::ActionCable.server.config.cable&.fetch("adapter", nil)
@@ -24,6 +28,29 @@ module AnyCable
24
28
  ADAPTER_ALIASES.include?(adapter)
25
29
  end
26
30
 
31
+ def with_socket_id(socket_id)
32
+ old_socket_id, self.current_socket_id = current_socket_id, socket_id
33
+ yield
34
+ ensure
35
+ self.current_socket_id = old_socket_id
36
+ end
37
+
38
+ def with_broadcast_options(**options)
39
+ old_options = current_broadcast_options
40
+ self.current_broadcast_options = options.reverse_merge(old_options || {})
41
+ yield
42
+ ensure
43
+ self.current_broadcast_options = old_options
44
+ end
45
+
46
+ def broadcasting_to_others(socket_id: nil, &block)
47
+ if socket_id
48
+ with_socket_id(socket_id) { with_broadcast_options(to_others: true, &block) }
49
+ else
50
+ with_broadcast_options(to_others: true, &block)
51
+ end
52
+ end
53
+
27
54
  # Serialize connection/channel state variable to string
28
55
  # using GlobalID where possible or JSON (if json: true)
29
56
  def serialize(obj, json: false)
@@ -50,9 +77,9 @@ module AnyCable
50
77
  end
51
78
 
52
79
  module Extension
53
- def broadcast(channel, payload)
80
+ def broadcast(...)
54
81
  super
55
- ::AnyCable.broadcast(channel, payload)
82
+ ::AnyCable.broadcast(...)
56
83
  end
57
84
  end
58
85
 
@@ -1,2 +1,11 @@
1
1
  Description:
2
2
  Configures your application to work with AnyCable interactively.
3
+
4
+ Example:
5
+ rails generate anycable:setup
6
+
7
+ # You can opt-in to use HTTP RPC
8
+ rails generate anycable:setup --rpc=http
9
+
10
+ # You can specify which version of anycable-go to use
11
+ rails generate anycable:setup --version=1.4
@@ -10,14 +10,15 @@ module AnyCableRailsGenerators
10
10
 
11
11
  DOCS_ROOT = "https://docs.anycable.io"
12
12
  DEVELOPMENT_METHODS = %w[skip local docker].freeze
13
- SERVER_SOURCES = %w[skip brew binary].freeze
13
+ RPC_IMPL = %w[grpc http].freeze
14
14
 
15
15
  class_option :devenv,
16
16
  type: :string,
17
17
  desc: "Select your development environment (options: #{DEVELOPMENT_METHODS.join(", ")})"
18
- class_option :source,
18
+ class_option :rpc,
19
19
  type: :string,
20
- desc: "Choose a way of installing AnyCable-Go server (options: #{SERVER_SOURCES.join(", ")})"
20
+ desc: "Select RPC implementation (options: #{RPC_IMPL.join(", ")})",
21
+ default: "grpc"
21
22
  class_option :skip_heroku,
22
23
  type: :boolean,
23
24
  desc: "Do not copy Heroku configs"
@@ -30,12 +31,6 @@ module AnyCableRailsGenerators
30
31
  class_option :skip_install,
31
32
  type: :boolean,
32
33
  desc: "Do not run bundle install when adding new gems"
33
-
34
- include WithOSHelpers
35
-
36
- class_option :bin_path,
37
- type: :string,
38
- desc: "Where to download AnyCable-Go server binary (default: #{DEFAULT_BIN_PATH})"
39
34
  class_option :version,
40
35
  type: :string,
41
36
  desc: "Specify the AnyCable-Go version (defaults to latest release)"
@@ -99,6 +94,7 @@ module AnyCableRailsGenerators
99
94
 
100
95
  in_root do
101
96
  next unless File.file?("Procfile")
97
+ next if http_rpc?
102
98
 
103
99
  contents = File.read("Procfile")
104
100
  contents.sub!(/^web: (.*)$/, %q(web: [[ "$ANYCABLE_DEPLOYMENT" == "true" ]] && bundle exec anycable --server-command="anycable-go" || \1))
@@ -171,6 +167,10 @@ module AnyCableRailsGenerators
171
167
  !!gemfile_lock&.match?(/^\s+rubocop\b/)
172
168
  end
173
169
 
170
+ def http_rpc?
171
+ options[:rpc] == "http"
172
+ end
173
+
174
174
  def gemfile_lock
175
175
  @gemfile_lock ||= begin
176
176
  res = nil
@@ -192,7 +192,7 @@ module AnyCableRailsGenerators
192
192
  say <<~YML
193
193
  ─────────────────────────────────────────
194
194
  ws:
195
- image: anycable/anycable-go:1.2
195
+ image: anycable/anycable-go:1.4
196
196
  ports:
197
197
  - '8080:8080'
198
198
  environment:
@@ -223,33 +223,25 @@ module AnyCableRailsGenerators
223
223
  end
224
224
 
225
225
  def install_for_local
226
- install_server
227
- template_proc_files
228
- end
229
-
230
- def install_server
231
- answer = SERVER_SOURCES.index(options[:source]) || 99
232
-
233
- until SERVER_SOURCES[answer.to_i]
234
- answer = ask "How do you want to install AnyCable-Go WebSocket server? (1) Homebrew, (2) Download binary, (0) Skip"
226
+ inside("bin") do
227
+ template "anycable-go", chmod: 0o755
235
228
  end
236
229
 
237
- case answer.to_i
238
- when 0
239
- say_status :help, "⚠️ Please, read this guide on how to install AnyCable-Go server 👉 #{DOCS_ROOT}/anycable-go/getting_started", :yellow
240
- return
241
- else
242
- return unless send("install_from_#{SERVER_SOURCES[answer.to_i]}")
230
+ if file_exists?(".gitignore")
231
+ append_file ".gitignore", "bin/dist\n"
243
232
  end
244
233
 
245
- say_status :info, "✅ AnyCable-Go WebSocket server has been successfully installed"
234
+ template_proc_files
246
235
  end
247
236
 
248
237
  def template_proc_files
249
238
  file_name = "Procfile.dev"
250
239
 
251
240
  if file_exists?(file_name)
252
- append_file file_name, "anycable: bundle exec anycable\nws: anycable-go#{anycable_go_options}", force: true
241
+ unless http_rpc?
242
+ append_file file_name, "anycable: bundle exec anycable\n", force: true
243
+ end
244
+ append_file file_name, "ws: bin/anycable-go #{anycable_go_options}", force: true
253
245
  else
254
246
  say_status :help, "💡 We recommend using Hivemind to manage multiple processes in development 👉 https://github.com/DarthSim/hivemind", :yellow
255
247
 
@@ -263,32 +255,11 @@ module AnyCableRailsGenerators
263
255
  end
264
256
  end
265
257
 
266
- def install_from_brew
267
- run "brew install anycable-go", abort_on_failure: true
268
- run "anycable-go -v", abort_on_failure: true
269
- end
270
-
271
- def install_from_binary
272
- bin_path ||= DEFAULT_BIN_PATH if options[:devenv] # User don't want interactive mode
273
- bin_path ||= ask "Please, enter the path to download the AnyCable-Go binary to", default: DEFAULT_BIN_PATH, path: true
274
-
275
- generate "anycable:download", download_options(bin_path: bin_path)
276
-
277
- true
278
- end
279
-
280
- def download_options(**params)
281
- opts = options.merge(params)
282
- [].tap do |args|
283
- args << "--os #{opts[:os]}" if opts[:os]
284
- args << "--cpu #{opts[:cpu]}" if opts[:cpu]
285
- args << "--bin-path=#{opts[:bin_path]}" if opts[:bin_path]
286
- args << "--version #{opts[:version]}" if opts[:version]
287
- end.join(" ")
288
- end
289
-
290
258
  def anycable_go_options
291
- redis? ? " --port=8080" : " --port=8080 --broadcast_adapter=http"
259
+ opts = ["--port=8080"]
260
+ opts << "--broadcast_adapter=http" unless redis?
261
+ opts << "--rpc_impl=http --rpc_host=http://localhost:3000/_anycable" if http_rpc?
262
+ opts.join(" ")
292
263
  end
293
264
 
294
265
  def file_exists?(name)
@@ -296,5 +267,18 @@ module AnyCableRailsGenerators
296
267
  return File.file?(name)
297
268
  end
298
269
  end
270
+
271
+ def anycable_go_version
272
+ @anycable_go_version ||= (normalize_version(options[:version]) || "latest")
273
+ end
274
+
275
+ def normalize_version(version)
276
+ return unless version
277
+
278
+ # We need a full version for bin/anycable-go script
279
+ segments = Gem::Version.new(version).segments
280
+ segments << 0 until segments.size >= 3
281
+ segments.join(".")
282
+ end
299
283
  end
300
284
  end
@@ -1,6 +1,5 @@
1
- server: bundle exec rails s
2
- <%- if webpacker? -%>
3
- assets: bundle exec bin/webpack-dev-server
4
- <%- end -%>
1
+ web: bin/rails s
2
+ <%- unless http_rpc? -%>
5
3
  anycable: bundle exec anycable
6
- ws: anycable-go<%= anycable_go_options %>
4
+ <%- end -%>
5
+ ws: bin/anycable-go <%= anycable_go_options %>
@@ -0,0 +1,22 @@
1
+ #!/bin/bash
2
+
3
+ cd $(dirname $0)/..
4
+
5
+ # It's recommended to use the exact version of AnyCable-Go here
6
+ version="<%= anycable_go_version %>"
7
+
8
+ if [ ! -f ./bin/dist/anycable-go ]; then
9
+ echo "AnyCable-go is not installed, downloading..."
10
+ ./bin/rails g anycable:download --version=$version --bin-path=./bin/dist
11
+ fi
12
+
13
+ curVersion=$(./bin/dist/anycable-go -v)
14
+
15
+ if [[ "$version" != "latest" ]]; then
16
+ if [[ "$curVersion" != "$version"* ]]; then
17
+ echo "AnyCable-go version is not $version, downloading a new one..."
18
+ ./bin/rails g anycable:download --version=$version --bin-path=./bin/dist
19
+ fi
20
+ fi
21
+
22
+ ./bin/dist/anycable-go $@
@@ -32,6 +32,9 @@ default: &default
32
32
  # Localhost is used by default.
33
33
  # redis_url: "redis://localhost:6379/1"
34
34
  <%- end -%>
35
+ <%- if http_rpc? -%>
36
+ http_rpc_mount_path: "/_anycable"
37
+ <%- end -%>
35
38
 
36
39
  development:
37
40
  <<: *default
@@ -41,8 +44,3 @@ test:
41
44
 
42
45
  production:
43
46
  <<: *default
44
- <%- if !redis? && !nats? -%>
45
- # Use Redis or NATS in production
46
- broadcast_adapter: redis
47
- # broadcast_adapter: nats
48
- <%- end -%>
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.4.0
4
+ version: 1.4.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - palkan
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-07-12 00:00:00.000000000 Z
11
+ date: 2023-10-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: anycable-core
@@ -66,6 +66,7 @@ files:
66
66
  - lib/action_cable/subscription_adapter/anycable.rb
67
67
  - lib/anycable-rails.rb
68
68
  - lib/anycable/rails.rb
69
+ - lib/anycable/rails/action_cable_ext/broadcast_options.rb
69
70
  - lib/anycable/rails/action_cable_ext/channel.rb
70
71
  - lib/anycable/rails/action_cable_ext/connection.rb
71
72
  - lib/anycable/rails/action_cable_ext/remote_connections.rb
@@ -86,12 +87,14 @@ files:
86
87
  - lib/anycable/rails/middlewares/log_tagging.rb
87
88
  - lib/anycable/rails/rack.rb
88
89
  - lib/anycable/rails/railtie.rb
90
+ - lib/anycable/rails/socket_id_tracking.rb
89
91
  - lib/anycable/rails/version.rb
90
92
  - lib/generators/anycable/download/USAGE
91
93
  - lib/generators/anycable/download/download_generator.rb
92
94
  - lib/generators/anycable/setup/USAGE
93
95
  - lib/generators/anycable/setup/setup_generator.rb
94
96
  - lib/generators/anycable/setup/templates/Procfile.dev.tt
97
+ - lib/generators/anycable/setup/templates/bin/anycable-go.tt
95
98
  - lib/generators/anycable/setup/templates/config/anycable.yml.tt
96
99
  - lib/generators/anycable/setup/templates/config/cable.yml.tt
97
100
  - lib/generators/anycable/setup/templates/config/initializers/anycable.rb.tt