anycable-rails-core 1.5.4 → 1.5.6

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: 6ceb26b8e5c09c7bd5500007a29a79a2933cc38848a63da16af272a4a5d11771
4
- data.tar.gz: 6db49c5ceca2e5b020fb7b225ebe2e1db63df8beb9858224502883ff35392529
3
+ metadata.gz: 06a551d757afa07138babbf351024554d52b667ab35893bc995cc1fb56edd8af
4
+ data.tar.gz: c630ecf586cfd0068b0d248c00dc1372ffd7d83a3abf0e76dc9ecd52ae960a7c
5
5
  SHA512:
6
- metadata.gz: d78c540124cec98c20e2004f49324580300a9be00eea194fa09200a8b30090b3448e3411dcba1a4002efa857997e0ed66da44a808efd17ceede3ce45fd97b751
7
- data.tar.gz: 4e7916ccc0f8c18ed305eab329575c1bc840be9eeeb1534d4d3c661067a5f9a96ac761af3e8f2f9871a0f3bcbc7d30816e09a3e9998d7bffdf3555d36a88f515
6
+ metadata.gz: 2d46a5b21269ef7cb9cfc562ecee2cfd9830e055dd18fb20bce468409f0a84bc3ca3dc1ba56d9d340202039de3ab93aeba2e600388b7130b99bff101cbf00448
7
+ data.tar.gz: 64a083bf7d4046b5a1bfa57058f0aa1cedded844067b15f5f9ea660a8d5291bbe2c8f6db6c4a63768f2d17f67d40bb920f4abe8e55b9fbc9241f72c4a4d9c587
data/CHANGELOG.md CHANGED
@@ -2,6 +2,12 @@
2
2
 
3
3
  ## master
4
4
 
5
+ ## 1.5.5 (2024-12-12)
6
+
7
+ - Publish RuboCop cops as a separate gem (`rubocop-anycable-rails`). ([@palkan][])
8
+
9
+ - Upgrade RuboCop cops. ([@palkan][])
10
+
5
11
  ## 1.5.4 (2024-10-08)
6
12
 
7
13
  - Add [actioncable-next](https://github.com/anycable/actioncable-next) support. ([@palkan][])
@@ -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
@@ -1,27 +1,4 @@
1
1
  # frozen_string_literal: true
2
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!
3
+ # For backwards compatibility
4
+ require_relative "../rubocop"
@@ -31,15 +31,65 @@ module AnyCable
31
31
  end
32
32
 
33
33
  refine ActionCable::Connection::Subscriptions do
34
- # Find or add a subscription to the list
35
- def fetch(identifier)
36
- add("identifier" => identifier) unless subscriptions[identifier]
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
- unless subscriptions[identifier]
39
- raise "Channel not found: #{ActiveSupport::JSON.decode(identifier).fetch("channel")}"
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
- subscriptions[identifier]
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.each do |id|
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
- # We cannot use subscriptions#execute_command here,
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
@@ -24,7 +24,7 @@ module RuboCop
24
24
  # end
25
25
  # end
26
26
  #
27
- class InstanceVars < RuboCop::Cop::Cop
27
+ class InstanceVars < RuboCop::Cop::Base
28
28
  MSG = "Channel instance variables are not supported in AnyCable. Use `state_attr_accessor` instead"
29
29
 
30
30
  def on_class(node)
@@ -13,7 +13,7 @@ module RuboCop
13
13
  # periodically(:do_something, every: 2.seconds)
14
14
  # end
15
15
  #
16
- class PeriodicalTimers < RuboCop::Cop::Cop
16
+ class PeriodicalTimers < RuboCop::Cop::Base
17
17
  MSG = "Periodical Timers are not supported in AnyCable"
18
18
 
19
19
  def_node_matcher :calls_periodically?, <<-PATTERN
@@ -34,7 +34,7 @@ module RuboCop
34
34
  # end
35
35
  # end
36
36
  #
37
- class StreamFrom < RuboCop::Cop::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!
@@ -2,6 +2,6 @@
2
2
 
3
3
  module AnyCable
4
4
  module Rails
5
- VERSION = "1.5.4"
5
+ VERSION = "1.5.6"
6
6
  end
7
7
  end
@@ -84,7 +84,7 @@ end
84
84
 
85
85
  # Warn if application has been already initialized.
86
86
  # AnyCable should be loaded before initialization in order to work correctly.
87
- if defined?(::Rails) && ::Rails.application && ::Rails.application.initialized?
87
+ if defined?(::Rails) && ::Rails.application&.initialized?
88
88
  puts("\n**************************************************")
89
89
  puts(
90
90
  "⛔️ WARNING: AnyCable loaded after application initialization. Might not work correctly.\n" \
@@ -23,7 +23,7 @@ default: &default
23
23
  <%- else -%>
24
24
  # Use HTTP broadcaster
25
25
  broadcast_adapter: http
26
- http_broadcast_url: "http://localhost:8090/_anycable"
26
+ http_broadcast_url: "http://localhost:8090/_broadcast"
27
27
  <%- end -%>
28
28
  <%- if redis? -%>
29
29
  # You can use REDIS_URL env var to configure Redis URL.
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.5.4
4
+ version: 1.5.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - palkan
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-10-09 00:00:00.000000000 Z
11
+ date: 2025-01-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: anycable-core
@@ -80,10 +80,6 @@ files:
80
80
  - lib/anycable/rails/channel_state.rb
81
81
  - lib/anycable/rails/compatibility.rb
82
82
  - lib/anycable/rails/compatibility/rubocop.rb
83
- - lib/anycable/rails/compatibility/rubocop/config/default.yml
84
- - lib/anycable/rails/compatibility/rubocop/cops/anycable/instance_vars.rb
85
- - lib/anycable/rails/compatibility/rubocop/cops/anycable/periodical_timers.rb
86
- - lib/anycable/rails/compatibility/rubocop/cops/anycable/stream_from.rb
87
83
  - lib/anycable/rails/config.rb
88
84
  - lib/anycable/rails/connection.rb
89
85
  - lib/anycable/rails/connection_factory.rb
@@ -105,6 +101,11 @@ files:
105
101
  - lib/anycable/rails/pubsub_channel.rb
106
102
  - lib/anycable/rails/rack.rb
107
103
  - lib/anycable/rails/railtie.rb
104
+ - lib/anycable/rails/rubocop.rb
105
+ - lib/anycable/rails/rubocop/config/default.yml
106
+ - lib/anycable/rails/rubocop/cops/anycable/instance_vars.rb
107
+ - lib/anycable/rails/rubocop/cops/anycable/periodical_timers.rb
108
+ - lib/anycable/rails/rubocop/cops/anycable/stream_from.rb
108
109
  - lib/anycable/rails/socket_id_tracking.rb
109
110
  - lib/anycable/rails/version.rb
110
111
  - lib/generators/anycable/bin/USAGE
@@ -130,7 +131,7 @@ metadata:
130
131
  homepage_uri: https://anycable.io/
131
132
  source_code_uri: http://github.com/anycable/anycable-rails
132
133
  funding_uri: https://github.com/sponsors/anycable
133
- post_install_message:
134
+ post_install_message:
134
135
  rdoc_options: []
135
136
  require_paths:
136
137
  - lib
@@ -146,7 +147,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
146
147
  version: '0'
147
148
  requirements: []
148
149
  rubygems_version: 3.4.19
149
- signing_key:
150
+ signing_key:
150
151
  specification_version: 4
151
152
  summary: AnyCable integration for Rails (w/o RPC dependencies)
152
153
  test_files: []