lex-node 0.3.5 → 0.3.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: b7ac92f5ed3cc4292a84de4981df2552a8b26c530ef8e0a8bbd496a6358d6145
4
- data.tar.gz: 6e1e6f020a74ff9f8850e8d1949e4d1e55a2dfdf874a1eb1be41749318f7eb70
3
+ metadata.gz: dc51c7fec2b526f23237c3c8da1c8457f7b10250ad7606a3d519049675025cc5
4
+ data.tar.gz: a0f8d664fdd16a3d16d64a948e3dfe2e8c27935251f1be5ffeef3bac21042220
5
5
  SHA512:
6
- metadata.gz: 9e7c9b1ad53d742abe5c44e4c49d4ea42ac142f4e55716b1cbb27ec3b61e7a7cc1f686fca6533be8f7b48c0d150cc1bf11b922f36dfbf3df2b02de2bc57b9638
7
- data.tar.gz: 4c63293aca829c8f862de742eb73b47c84486a361f813a34cb7aba2012027734fcdfbb96731dfd04ad1e4694660654c47f552398ef5cdf23644bab5516890212
6
+ metadata.gz: fd71f5b8d3152d625af005aef5add980d90548d6299bf7f6afd93b69585941b69c37b29ecc882d9325a0075d0fc60b744c9080305e2375350714f3a8cfcb52ba
7
+ data.tar.gz: c127f5a0b891e70df65b4639588a628596c8207ec31a21529bee8f39117c4cbf36b4d202d27b2619224e815035291bd8c8b81015f1a369071ff1041a8339d770
data/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.3.6] - 2026-03-31
4
+
5
+ ### Added
6
+ - `legion.cluster.control` topic exchange for cluster-wide broadcast (durable, topic type)
7
+ - Per-node auto-delete queue `legion.cluster.control.<name>` bound to the exchange on boot
8
+ - `ClusterSettings` message: publishes settings changes with configurable routing key to the cluster control exchange
9
+ - `ClusterKillswitch` message: publishes emergency extension block via routing key `settings.extensions.blocked`
10
+ - `ClusterControl` subscription actor: subscribes to the per-node cluster control queue, routes to existing runners by routing key
11
+ - `Runners::Node#broadcast_settings(settings:, routing_key: 'settings', restart: false)`: sends settings to all nodes via the cluster control exchange
12
+ - `Runners::Node#killswitch(extension:)`: blocks an extension cluster-wide with immediate reload
13
+ - 51 new specs covering all new components (162 total, 0 failures)
14
+
3
15
  ## [0.3.5] - 2026-03-30
4
16
 
5
17
  ### Changed
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module Node
6
+ module Actor
7
+ class ClusterControl < Legion::Extensions::Actors::Subscription
8
+ def runner_class
9
+ Legion::Extensions::Node::Runners::Node
10
+ end
11
+
12
+ def queue_class
13
+ Legion::Extensions::Node::Transport::Queues::ClusterControl
14
+ end
15
+
16
+ def disabled?
17
+ false
18
+ end
19
+
20
+ def use_runner?
21
+ true
22
+ end
23
+
24
+ def check_subtask?
25
+ false
26
+ end
27
+
28
+ def generate_task?
29
+ false
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -120,6 +120,30 @@ module Legion
120
120
  public_key: public_key)
121
121
  end
122
122
 
123
+ def broadcast_settings(settings:, routing_key: 'settings', restart: false, **_opts)
124
+ log.debug "broadcast_settings: routing_key=#{routing_key} keys=#{settings.keys.join(', ')}"
125
+ Legion::Extensions::Node::Transport::Messages::ClusterSettings.new(
126
+ settings: settings,
127
+ routing_key: routing_key,
128
+ restart: restart
129
+ ).publish
130
+ {}
131
+ rescue StandardError => e
132
+ log.error "broadcast_settings failed: #{e.message}"
133
+ {}
134
+ end
135
+
136
+ def killswitch(extension:, **_opts)
137
+ log.debug "killswitch: blocking extension #{extension} cluster-wide"
138
+ Legion::Extensions::Node::Transport::Messages::ClusterKillswitch.new(
139
+ extension: extension.to_s.delete_prefix('lex-')
140
+ ).publish
141
+ {}
142
+ rescue StandardError => e
143
+ log.error "killswitch failed: #{e.message}"
144
+ {}
145
+ end
146
+
123
147
  private
124
148
 
125
149
  def publish_update_result(action:, status:, detail: nil, error: nil)
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module Node
6
+ module Transport
7
+ module Exchanges
8
+ class ClusterControl
9
+ EXCHANGE_NAME = 'legion.cluster.control'
10
+ EXCHANGE_TYPE = :topic
11
+ EXCHANGE_OPTIONS = { durable: true }.freeze
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module Node
6
+ module Transport
7
+ module Messages
8
+ class ClusterKillswitch < Legion::Transport::Message
9
+ ROUTING_KEY = 'settings.extensions.blocked'
10
+
11
+ def routing_key
12
+ ROUTING_KEY
13
+ end
14
+
15
+ def exchange
16
+ Legion::Extensions::Node::Transport::Exchanges::ClusterControl
17
+ end
18
+
19
+ def type
20
+ 'task'
21
+ end
22
+
23
+ def encrypt?
24
+ false
25
+ end
26
+
27
+ def message
28
+ {
29
+ function: 'update_settings',
30
+ settings: { extensions: { blocked: [@options[:extension]] } },
31
+ restart: true
32
+ }
33
+ end
34
+
35
+ def validate
36
+ raise 'extension must be a String' unless @options[:extension].is_a?(String)
37
+
38
+ @valid = true
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module Node
6
+ module Transport
7
+ module Messages
8
+ class ClusterSettings < Legion::Transport::Message
9
+ def routing_key
10
+ @options.fetch(:routing_key, 'settings')
11
+ end
12
+
13
+ def exchange
14
+ Legion::Extensions::Node::Transport::Exchanges::ClusterControl
15
+ end
16
+
17
+ def type
18
+ 'task'
19
+ end
20
+
21
+ def encrypt?
22
+ false
23
+ end
24
+
25
+ def message
26
+ {
27
+ function: 'update_settings',
28
+ settings: @options[:settings],
29
+ restart: @options.fetch(:restart, false)
30
+ }
31
+ end
32
+
33
+ def validate
34
+ raise 'settings must be a Hash' unless @options[:settings].is_a?(Hash)
35
+
36
+ @valid = true
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module Node
6
+ module Transport
7
+ module Queues
8
+ class ClusterControl < Legion::Transport::Queue
9
+ def queue_name
10
+ "legion.cluster.control.#{Legion::Settings[:client][:name]}"
11
+ end
12
+
13
+ def queue_options
14
+ { durable: false, exclusive: false, auto_delete: true,
15
+ arguments: { 'x-queue-type': 'classic' } }
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -13,6 +13,7 @@ module Legion
13
13
  array.push(from: 'node', to: 'node', routing_key: 'node.data.#') if Legion::Settings[:data]&.[](:connected) || false
14
14
  array.push(from: 'node', to: 'node', routing_key: 'node.cache.#') if Legion::Settings[:cache]&.[](:connected) || false
15
15
  array.push(from: 'node', to: 'node', routing_key: 'node.crypt.#')
16
+ array.push(from: 'cluster_control', to: 'cluster_control', routing_key: '#')
16
17
  array
17
18
  end
18
19
  end
@@ -3,7 +3,7 @@
3
3
  module Legion
4
4
  module Extensions
5
5
  module Node
6
- VERSION = '0.3.5'
6
+ VERSION = '0.3.6'
7
7
  end
8
8
  end
9
9
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lex-node
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.5
4
+ version: 0.3.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Esity
@@ -145,6 +145,7 @@ files:
145
145
  - lex-node.gemspec
146
146
  - lib/legion/extensions/node.rb
147
147
  - lib/legion/extensions/node/actors/beat.rb
148
+ - lib/legion/extensions/node/actors/cluster_control.rb
148
149
  - lib/legion/extensions/node/actors/crypt.rb
149
150
  - lib/legion/extensions/node/actors/push_key.rb
150
151
  - lib/legion/extensions/node/actors/vault.rb
@@ -160,8 +161,11 @@ files:
160
161
  - lib/legion/extensions/node/runners/node.rb
161
162
  - lib/legion/extensions/node/runners/vault.rb
162
163
  - lib/legion/extensions/node/transport.rb
164
+ - lib/legion/extensions/node/transport/exchanges/cluster_control.rb
163
165
  - lib/legion/extensions/node/transport/exchanges/node.rb
164
166
  - lib/legion/extensions/node/transport/messages/beat.rb
167
+ - lib/legion/extensions/node/transport/messages/cluster_killswitch.rb
168
+ - lib/legion/extensions/node/transport/messages/cluster_settings.rb
165
169
  - lib/legion/extensions/node/transport/messages/public_key.rb
166
170
  - lib/legion/extensions/node/transport/messages/push_cluster_secret.rb
167
171
  - lib/legion/extensions/node/transport/messages/push_vault_token.rb
@@ -169,6 +173,7 @@ files:
169
173
  - lib/legion/extensions/node/transport/messages/request_public_keys.rb
170
174
  - lib/legion/extensions/node/transport/messages/request_vault_token.rb
171
175
  - lib/legion/extensions/node/transport/messages/update_result.rb
176
+ - lib/legion/extensions/node/transport/queues/cluster_control.rb
172
177
  - lib/legion/extensions/node/transport/queues/crypt.rb
173
178
  - lib/legion/extensions/node/transport/queues/health.rb
174
179
  - lib/legion/extensions/node/transport/queues/node.rb