anycable-rails-core 1.5.4 → 1.5.6

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: 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: []