anycable-rails 1.0.0.rc1 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 36b6e47a498bfc2d1156e4635a5c30f60258c925142c59ad837c1b6708f1ff73
4
- data.tar.gz: f27c94856df0db9d178537e8ac75598f8a355b338e725a80a5cb06a6e0ac610c
3
+ metadata.gz: d2c1f822cbb79135290b3c404544d937f0f083751657057b7bdd4445a33a95f1
4
+ data.tar.gz: ae4f5e42da49c8f668ee2cf56a434e30872d04cee9bc3596f914fb2e48404ac1
5
5
  SHA512:
6
- metadata.gz: 28b72e3f6a9950d3a95eb8d4f1c6a59f24a704ff63ac50384ffb2d22aa97c9f6b6e1f0c882a89cc6a0fd9ac22ea553a381514d56885f6f1cce41e7146153ab24
7
- data.tar.gz: ac7c402d2b57a332ced9372a4546709d6b41a0fb082c823d292b87c8b11e4bf741047cbc10258f68acd228712f0ca974b6723246bd3ddc689920f656b1488974
6
+ metadata.gz: 55bb99bacfdbd2b29120e29598aedc467f56325096602c7713bc2bfee9c4c40f826089ee4dd4d76e80d7171bdd1989db0d21c002edae0e429174509d24f8d836
7
+ data.tar.gz: 2ee8318ebd5c27dd95b21bd784c75d0d78da08538f1dd466235b889485d2229a4f35202b036a422466f38422905fbda16f84a028ecb3772e0669ce2bfc203dda
@@ -1,6 +1,27 @@
1
1
  # Change log
2
2
 
3
- ## 1.0.0.rc1 (2020-06-10)
3
+ ## master
4
+
5
+ ## 1.0.1 (2020-07-07)
6
+
7
+ - Fixed patching Action Cable testing classes. ([@palkan][])
8
+
9
+ ## 1.0.0 (2020-07-01)
10
+
11
+ - Support `rescue_from` in connections (Rails 6.1). ([@palkan][])
12
+
13
+ - Make AnyCable patches compatible with Action Cable testing. ([@palkan][])
14
+
15
+ - Do not add localhost `redis_url` to `anycable.yml` when Docker development method is chosen in `anycable:setup`. ([@palkan][])
16
+
17
+ - Fix connection identifiers deserialization regression. ([@palkan][])
18
+
19
+ Using non-strings or non-GlobalId-encoded objects was broken.
20
+
21
+ - Improve `anycable:setup` generator. ([@palkan][])
22
+
23
+ Update Docker snippet, do not enable persistent sessions automatically,
24
+ fix setting `config.action_cable.url` in environment configuration.
4
25
 
5
26
  - Add `state_attr_accessor` for channels. ([@palkan][])
6
27
 
@@ -35,7 +35,7 @@ module AnyCable
35
35
  # If the resulting object is a Hash, make it indifferent
36
36
  def deserialize(str, json: false)
37
37
  str.yield_self do |val|
38
- next unless val.is_a?(String)
38
+ next val unless val.is_a?(String)
39
39
 
40
40
  gval = GlobalID::Locator.locate(val)
41
41
  return gval if gval
@@ -21,6 +21,8 @@ module ActionCable
21
21
 
22
22
  attr_reader :socket
23
23
 
24
+ alias anycable_socket socket
25
+
24
26
  delegate :env, :session, to: :request
25
27
 
26
28
  class << self
@@ -196,3 +198,18 @@ module ActionCable
196
198
  # rubocop:enable Metrics/ClassLength
197
199
  end
198
200
  end
201
+
202
+ # Support rescue_from
203
+ # https://github.com/rails/rails/commit/d2571e560c62116f60429c933d0c41a0e249b58b
204
+ if ActionCable::Connection::Base.respond_to?(:rescue_from)
205
+ ActionCable::Connection::Base.prepend(Module.new do
206
+ def handle_channel_command(*)
207
+ super
208
+ rescue Exception => e # rubocop:disable Lint/RescueException
209
+ rescue_with_handler(e) || raise
210
+ false
211
+ end
212
+ end)
213
+ end
214
+
215
+ require "anycable/rails/actioncable/testing" if ::Rails.env.test?
@@ -15,16 +15,20 @@ module ActionCable
15
15
  return super unless socket.session
16
16
 
17
17
  super.tap do |req|
18
- req.env[Rack::RACK_SESSION] =
19
- AnyCable::Rails::SessionProxy.new(req.env[Rack::RACK_SESSION], socket.session)
18
+ req.env[::Rack::RACK_SESSION] =
19
+ AnyCable::Rails::SessionProxy.new(req.env[::Rack::RACK_SESSION], socket.session)
20
20
  end
21
21
  end
22
22
 
23
23
  def commit_session!
24
- return unless request_loaded? && request.session.loaded?
24
+ return unless request_loaded? && request.session.respond_to?(:loaded?) && request.session.loaded?
25
25
 
26
26
  socket.session = request.session.to_json
27
27
  end
28
28
  end
29
29
  end
30
30
  end
31
+
32
+ ::ActionCable::Connection::Base.prepend(
33
+ ::ActionCable::Connection::PersistentSession
34
+ )
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This file contains patches to Action Cable testing modules
4
+
5
+ # Trigger autoload (if constant is defined)
6
+ begin
7
+ ActionCable::Channel::TestCase # rubocop:disable Lint/Void
8
+ ActionCable::Connection::TestCase # rubocop:disable Lint/Void
9
+ rescue NameError
10
+ return
11
+ end
12
+
13
+ ActionCable::Channel::ChannelStub.prepend(Module.new do
14
+ def subscribe_to_channel
15
+ # allocate @streams
16
+ streams
17
+ handle_subscribe
18
+ end
19
+ end)
20
+
21
+ ActionCable::Channel::ConnectionStub.prepend(Module.new do
22
+ def socket
23
+ @socket ||= AnyCable::Socket.new(env: {})
24
+ end
25
+
26
+ alias_method :anycable_socket, :socket
27
+ end)
28
+
29
+ ActionCable::Connection::TestConnection.prepend(Module.new do
30
+ def initialize(request)
31
+ @request = request
32
+ @cached_ids = {}
33
+ super
34
+ end
35
+ end)
@@ -5,18 +5,16 @@ module AnyCable
5
5
  module ChannelState
6
6
  module ClassMethods
7
7
  def state_attr_accessor(*names)
8
- return attr_accessor(*names) unless AnyCable::Rails.enabled?
9
-
10
8
  names.each do |name|
11
9
  channel_state_attributes << name
12
10
  class_eval <<~RUBY, __FILE__, __LINE__ + 1
13
11
  def #{name}
14
12
  return @#{name} if instance_variable_defined?(:@#{name})
15
- @#{name} = AnyCable::Rails.deserialize(connection.socket.istate["#{name}"], json: true)
13
+ @#{name} = AnyCable::Rails.deserialize(connection.socket.istate["#{name}"], json: true) if connection.anycable_socket
16
14
  end
17
15
 
18
16
  def #{name}=(val)
19
- connection.socket.istate["#{name}"] = AnyCable::Rails.serialize(val, json: true)
17
+ connection.socket.istate["#{name}"] = AnyCable::Rails.serialize(val, json: true) if connection.anycable_socket
20
18
  instance_variable_set(:@#{name}, val)
21
19
  end
22
20
  RUBY
@@ -43,18 +43,18 @@ module AnyCable
43
43
 
44
44
  initializer "anycable.connection_factory", after: "action_cable.set_configs" do |app|
45
45
  ActiveSupport.on_load(:action_cable) do
46
+ # Add AnyCable patch method stub (we use it in ChannelState to distinguish between Action Cable and AnyCable)
47
+ # NOTE: Method could be already defined if patch was loaded manually
48
+ ActionCable::Connection::Base.attr_reader(:anycable_socket) unless ActionCable::Connection::Base.method_defined?(:anycable_socket)
49
+
50
+ app.config.to_prepare do
51
+ AnyCable.connection_factory = ActionCable.server.config.connection_class.call
52
+ end
53
+
46
54
  if AnyCable::Rails.enabled?
47
55
  require "anycable/rails/actioncable/connection"
48
-
49
56
  if AnyCable.config.persistent_session_enabled
50
57
  require "anycable/rails/actioncable/connection/persistent_session"
51
- ::ActionCable::Connection::Base.prepend(
52
- ::ActionCable::Connection::PersistentSession
53
- )
54
- end
55
-
56
- app.config.to_prepare do
57
- AnyCable.connection_factory = ActionCable.server.config.connection_class.call
58
58
  end
59
59
  end
60
60
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module AnyCable
4
4
  module Rails
5
- VERSION = "1.0.0.rc1"
5
+ VERSION = "1.0.1"
6
6
  end
7
7
  end
@@ -1,5 +1,5 @@
1
1
  Description:
2
- Install AnyCable-Go web server.
2
+ Install AnyCable-Go web server locally (the latest version by default).
3
3
 
4
4
  Example:
5
5
  rails generate anycable:download
@@ -9,8 +9,7 @@ module AnyCableRailsGenerators
9
9
 
10
10
  include WithOSHelpers
11
11
 
12
- # TODO: change to latest release
13
- VERSION = "1.0.0.preview1"
12
+ VERSION = "latest"
14
13
 
15
14
  class_option :bin_path,
16
15
  type: :string,
@@ -35,20 +34,27 @@ module AnyCableRailsGenerators
35
34
  private
36
35
 
37
36
  def release_url(version)
37
+ return latest_release_url(version) if version == "latest"
38
+
38
39
  if Gem::Version.new(version).segments.first >= 1
39
- new_release_url(version)
40
+ new_release_url("v#{version}")
40
41
  else
41
- legacy_release_url(version)
42
+ legacy_release_url("v#{version}")
42
43
  end
43
44
  end
44
45
 
45
46
  def legacy_release_url(version)
46
- "https://github.com/anycable/anycable-go/releases/download/v#{version}/" \
47
+ "https://github.com/anycable/anycable-go/releases/download/#{version}/" \
47
48
  "anycable-go-v#{version}-#{os_name}-#{cpu_name}"
48
49
  end
49
50
 
50
51
  def new_release_url(version)
51
- "https://github.com/anycable/anycable-go/releases/download/v#{version}/" \
52
+ "https://github.com/anycable/anycable-go/releases/download/#{version}/" \
53
+ "anycable-go-#{os_name}-#{cpu_name}"
54
+ end
55
+
56
+ def latest_release_url(version)
57
+ "https://github.com/anycable/anycable-go/releases/latest/download/" \
52
58
  "anycable-go-#{os_name}-#{cpu_name}"
53
59
  end
54
60
 
@@ -49,14 +49,18 @@ module AnyCableRailsGenerators
49
49
  environment(nil, env: :development) do
50
50
  <<~SNIPPET
51
51
  # Specify AnyCable WebSocket server URL to use by JS client
52
- config.action_cable.url = ENV.fetch("CABLE_URL", "ws://localhost:8080/cable") if AnyCable::Rails.enabled?
52
+ config.after_initialize do
53
+ config.action_cable.url = ActionCable.server.config.url = ENV.fetch("CABLE_URL", "ws://localhost:8080/cable") if AnyCable::Rails.enabled?
54
+ end
53
55
  SNIPPET
54
56
  end
55
57
 
56
58
  environment(nil, env: :production) do
57
59
  <<~SNIPPET
58
60
  # Specify AnyCable WebSocket server URL to use by JS client
59
- config.action_cable.url = ENV.fetch("CABLE_URL") if AnyCable::Rails.enabled?
61
+ config.after_initialize do
62
+ config.action_cable.url = ActionCable.server.config.url = ENV.fetch("CABLE_URL") if AnyCable::Rails.enabled?
63
+ end
60
64
  SNIPPET
61
65
  end
62
66
 
@@ -111,6 +115,12 @@ module AnyCableRailsGenerators
111
115
  say_status :info, "✅ config/initializers/anycable.rb with Devise configuration has been added"
112
116
  end
113
117
 
118
+ def stimulus_reflex
119
+ return unless stimulus_reflex?
120
+
121
+ say_status :help, "⚠️ Please, check out the documentation on using AnyCable with Stimulus Reflex: https://docs.anycable.io/v1/#/ruby/stimulus_reflex"
122
+ end
123
+
114
124
  def rubocop_compatibility
115
125
  return unless rubocop?
116
126
 
@@ -133,6 +143,10 @@ module AnyCableRailsGenerators
133
143
  !!gemfile_lock&.match?(/^\s+redis\b/)
134
144
  end
135
145
 
146
+ def webpacker?
147
+ !!gemfile_lock&.match?(/^\s+webpacker\b/)
148
+ end
149
+
136
150
  def rubocop?
137
151
  !!gemfile_lock&.match?(/^\s+rubocop\b/)
138
152
  end
@@ -149,21 +163,26 @@ module AnyCableRailsGenerators
149
163
  end
150
164
 
151
165
  def install_for_docker
166
+ # Remove localhost from configuraiton
167
+ gsub_file "config/anycable.yml", /^.*redis_url:.*localhost[^\n]+\n/, ""
168
+
152
169
  say_status :help, "️️⚠️ Docker development configuration could vary", :yellow
153
170
 
154
171
  say "Here is an example snippet for docker-compose.yml:"
155
172
  say <<~YML
156
173
  ─────────────────────────────────────────
157
174
  ws:
158
- image: anycable/anycable-go:1.0.0.preview1
175
+ image: anycable/anycable-go:1.0
159
176
  ports:
160
177
  - '8080:8080'
161
178
  environment:
179
+ ANYCABLE_HOST: "0.0.0.0"
162
180
  ANYCABLE_REDIS_URL: redis://redis:6379/0
163
181
  ANYCABLE_RPC_HOST: anycable:50051
182
+ ANYCABLE_DEBUG: 1
164
183
  depends_on:
165
- - anycable-rpc
166
- - redis
184
+ redis:
185
+ condition: service_healthy
167
186
 
168
187
  anycable:
169
188
  <<: *backend
@@ -172,8 +191,13 @@ module AnyCableRailsGenerators
172
191
  <<: *backend_environment
173
192
  ANYCABLE_REDIS_URL: redis://redis:6379/0
174
193
  ANYCABLE_RPC_HOST: 0.0.0.0:50051
194
+ ANYCABLE_DEBUG: 1
175
195
  ports:
176
196
  - '50051'
197
+ depends_on:
198
+ <<: *backend_depends_on
199
+ ws:
200
+ condition: service_started
177
201
  ─────────────────────────────────────────
178
202
  YML
179
203
  end
@@ -204,8 +228,8 @@ module AnyCableRailsGenerators
204
228
  def template_proc_files
205
229
  file_name = "Procfile.dev"
206
230
 
207
- if File.exist?(file_name)
208
- append_file file_name, 'anycable: bundle exec anycable --server-command "anycable-go --port 3334"'
231
+ if file_exists?(file_name)
232
+ append_file file_name, "anycable: bundle exec anycable\nws: anycable-go#{anycable_go_options}", force: true
209
233
  else
210
234
  say_status :help, "💡 We recommend using Hivemind to manage multiple processes in development 👉 https://github.com/DarthSim/hivemind", :yellow
211
235
 
@@ -242,5 +266,15 @@ module AnyCableRailsGenerators
242
266
  args << "--version #{opts[:version]}" if opts[:version]
243
267
  end.join(" ")
244
268
  end
269
+
270
+ def anycable_go_options
271
+ redis? ? " --port=8080" : " --port=8080 --broadcast_adapter=http"
272
+ end
273
+
274
+ def file_exists?(name)
275
+ in_root do
276
+ return File.file?(name)
277
+ end
278
+ end
245
279
  end
246
280
  end
@@ -0,0 +1,6 @@
1
+ server: bundle exec rails s
2
+ <%- if webpacker? -%>
3
+ assets: bundle exec bin/webpack-dev-server
4
+ <%- end -%>
5
+ anycable: bundle exec anycable
6
+ ws: anycable-go<%= anycable_go_options %>
@@ -12,8 +12,8 @@
12
12
  default: &default
13
13
  # Turn on/off access logs ("Started..." and "Finished...")
14
14
  access_logs_disabled: false
15
- # Persist "dirty" session between RPC calls (might be required for StimulusReflex apps)
16
- persistent_session_enabled: <%= stimulus_reflex? %>
15
+ # Persist "dirty" session between RPC calls (might be required for apps using stimulus_reflex <3.0)
16
+ # persistent_session_enabled: true
17
17
  # This is the host and the port to run AnyCable RPC server on.
18
18
  # You must configure your WebSocket server to connect to it, e.g.:
19
19
  # $ anycable-go --rpc-host="<rpc hostname>:50051"
@@ -30,10 +30,17 @@ default: &default
30
30
  # Use the same channel name for WebSocket server, e.g.:
31
31
  # $ anycable-go --redis-channel="__anycable__"
32
32
  redis_channel: "__anycable__"
33
+ <%- if redis? -%>
34
+ # You can use REDIS_URL env var to configure Redis URL.
35
+ # Localhost is used by default.
36
+ # redis_url: "redis://localhost:6379/1"
37
+ <%- end -%>
33
38
 
34
39
  development:
35
40
  <<: *default
36
- redis_url: "redis://localhost:6379/1"
41
+
42
+ test:
43
+ <<: *default
37
44
 
38
45
  production:
39
46
  <<: *default
metadata CHANGED
@@ -1,29 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: anycable-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0.rc1
4
+ version: 1.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - palkan
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-06-10 00:00:00.000000000 Z
11
+ date: 2020-07-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: anycable
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - '='
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: 1.0.0.rc1
19
+ version: 1.0.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - '='
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: 1.0.0.rc1
26
+ version: 1.0.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rails
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -81,19 +81,19 @@ dependencies:
81
81
  - !ruby/object:Gem::Version
82
82
  version: '13.0'
83
83
  - !ruby/object:Gem::Dependency
84
- name: rspec
84
+ name: rspec-rails
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
87
  - - ">="
88
88
  - !ruby/object:Gem::Version
89
- version: '3.4'
89
+ version: 4.0.0
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - ">="
95
95
  - !ruby/object:Gem::Version
96
- version: '3.4'
96
+ version: 4.0.0
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: rubocop
99
99
  requirement: !ruby/object:Gem::Requirement
@@ -141,6 +141,7 @@ files:
141
141
  - lib/anycable/rails/actioncable/connection/persistent_session.rb
142
142
  - lib/anycable/rails/actioncable/connection/serializable_identification.rb
143
143
  - lib/anycable/rails/actioncable/remote_connections.rb
144
+ - lib/anycable/rails/actioncable/testing.rb
144
145
  - lib/anycable/rails/channel_state.rb
145
146
  - lib/anycable/rails/compatibility.rb
146
147
  - lib/anycable/rails/compatibility/rubocop.rb
@@ -160,7 +161,7 @@ files:
160
161
  - lib/generators/anycable/download/download_generator.rb
161
162
  - lib/generators/anycable/setup/USAGE
162
163
  - lib/generators/anycable/setup/setup_generator.rb
163
- - lib/generators/anycable/setup/templates/Procfile.dev
164
+ - lib/generators/anycable/setup/templates/Procfile.dev.tt
164
165
  - lib/generators/anycable/setup/templates/config/anycable.yml.tt
165
166
  - lib/generators/anycable/setup/templates/config/cable.yml.tt
166
167
  - lib/generators/anycable/setup/templates/config/initializers/anycable.rb.tt
@@ -185,9 +186,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
185
186
  version: '2.5'
186
187
  required_rubygems_version: !ruby/object:Gem::Requirement
187
188
  requirements:
188
- - - ">"
189
+ - - ">="
189
190
  - !ruby/object:Gem::Version
190
- version: 1.3.1
191
+ version: '0'
191
192
  requirements: []
192
193
  rubygems_version: 3.0.6
193
194
  signing_key:
@@ -1,3 +0,0 @@
1
- server: bin/rails server
2
- assets: bin/webpack-dev-server
3
- anycable: bundle exec anycable --server-command "anycable-go --port 3334"