lex-node 0.2.0 → 0.2.3

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.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +16 -0
  3. data/.rubocop.yml +40 -10
  4. data/CHANGELOG.md +19 -0
  5. data/CLAUDE.md +109 -0
  6. data/Dockerfile +1 -1
  7. data/Gemfile +2 -0
  8. data/Gemfile.lock +87 -0
  9. data/README.md +65 -5
  10. data/docker_deploy.rb +1 -0
  11. data/lex-node.gemspec +4 -1
  12. data/lib/legion/extensions/node/actors/beat.rb +27 -19
  13. data/lib/legion/extensions/node/actors/crypt.rb +12 -4
  14. data/lib/legion/extensions/node/actors/push_key.rb +27 -19
  15. data/lib/legion/extensions/node/actors/vault.rb +27 -19
  16. data/lib/legion/extensions/node/actors/vault_token_request.rb +27 -19
  17. data/lib/legion/extensions/node/data_test/migrations/001_nodes_table.rb +2 -0
  18. data/lib/legion/extensions/node/data_test/migrations/002_node_history_table.rb +2 -1
  19. data/lib/legion/extensions/node/data_test/migrations/003_legion_version_colume.rb +2 -0
  20. data/lib/legion/extensions/node/data_test/migrations/004_node_extensions.rb +2 -1
  21. data/lib/legion/extensions/node/runners/beat.rb +17 -9
  22. data/lib/legion/extensions/node/runners/crypt.rb +60 -52
  23. data/lib/legion/extensions/node/runners/node.rb +109 -52
  24. data/lib/legion/extensions/node/runners/vault.rb +44 -36
  25. data/lib/legion/extensions/node/transport/exchanges/node.rb +12 -6
  26. data/lib/legion/extensions/node/transport/messages/beat.rb +85 -22
  27. data/lib/legion/extensions/node/transport/messages/public_key.rb +24 -14
  28. data/lib/legion/extensions/node/transport/messages/push_cluster_secret.rb +34 -24
  29. data/lib/legion/extensions/node/transport/messages/push_vault_token.rb +34 -24
  30. data/lib/legion/extensions/node/transport/messages/request_cluster_secret.rb +26 -16
  31. data/lib/legion/extensions/node/transport/messages/request_public_keys.rb +23 -13
  32. data/lib/legion/extensions/node/transport/messages/request_vault_token.rb +31 -21
  33. data/lib/legion/extensions/node/transport/messages/update_result.rb +36 -0
  34. data/lib/legion/extensions/node/transport/queues/crypt.rb +14 -4
  35. data/lib/legion/extensions/node/transport/queues/health.rb +14 -4
  36. data/lib/legion/extensions/node/transport/queues/node.rb +18 -7
  37. data/lib/legion/extensions/node/transport/queues/vault.rb +14 -4
  38. data/lib/legion/extensions/node/transport.rb +17 -8
  39. data/lib/legion/extensions/node/version.rb +3 -1
  40. data/lib/legion/extensions/node.rb +2 -0
  41. metadata +10 -9
  42. data/.github/workflows/rspec.yml +0 -69
  43. data/.github/workflows/rubocop.yml +0 -28
@@ -1,27 +1,35 @@
1
- module Legion::Extensions::Node::Actor
2
- class VaultTokenRequest < Legion::Extensions::Actors::Once
3
- def runner_function
4
- 'request_token'
5
- end
1
+ # frozen_string_literal: true
6
2
 
7
- def runner_class
8
- Legion::Extensions::Node::Runners::Vault
9
- end
3
+ module Legion
4
+ module Extensions
5
+ module Node
6
+ module Actor
7
+ class VaultTokenRequest < Legion::Extensions::Actors::Once
8
+ def runner_function
9
+ 'request_token'
10
+ end
10
11
 
11
- def use_runner?
12
- false
13
- end
12
+ def runner_class
13
+ Legion::Extensions::Node::Runners::Vault
14
+ end
14
15
 
15
- def check_subtask?
16
- false
17
- end
16
+ def use_runner?
17
+ false
18
+ end
18
19
 
19
- def generate_task?
20
- false
21
- end
20
+ def check_subtask?
21
+ false
22
+ end
23
+
24
+ def generate_task?
25
+ false
26
+ end
22
27
 
23
- def delay
24
- 0
28
+ def delay
29
+ 0
30
+ end
31
+ end
32
+ end
25
33
  end
26
34
  end
27
35
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  Sequel.migration do
2
4
  up do
3
5
  run "CREATE TABLE `nodes` (
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  Sequel.migration do
2
4
  up do
3
5
  run "
@@ -23,4 +25,3 @@ Sequel.migration do
23
25
  drop_table :node_history
24
26
  end
25
27
  end
26
-
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  Sequel.migration do
2
4
  change do
3
5
  alter_table(:nodes) do
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  Sequel.migration do
2
4
  up do
3
5
  run "
@@ -20,4 +22,3 @@ Sequel.migration do
20
22
  drop_table :node_extensions
21
23
  end
22
24
  end
23
-
@@ -1,13 +1,21 @@
1
- module Legion::Extensions::Node::Runners
2
- module Beat
3
- include Legion::Extensions::Helpers::Transport
1
+ # frozen_string_literal: true
4
2
 
5
- def beat(status: 'active', **opts)
6
- log.debug 'sending hearbeat'
7
- messages::Beat.new(status: status).publish
8
- { success: true, status: status, version: Legion::VERSION || nil, **opts }
9
- end
3
+ module Legion
4
+ module Extensions
5
+ module Node
6
+ module Runners
7
+ module Beat
8
+ include Legion::Extensions::Helpers::Transport
9
+
10
+ def beat(status: 'active', **opts)
11
+ log.debug 'sending hearbeat'
12
+ messages::Beat.new(status: status).publish
13
+ { success: true, status: status, version: Legion::VERSION || nil, **opts }
14
+ end
10
15
 
11
- include Legion::Extensions::Helpers::Lex
16
+ include Legion::Extensions::Helpers::Lex
17
+ end
18
+ end
19
+ end
12
20
  end
13
21
  end
@@ -1,61 +1,69 @@
1
- module Legion::Extensions::Node::Runners
2
- module Crypt
3
- def push_public_key(**_opts)
4
- log.debug 'push_public_key'
5
- message_hash = { function: 'update_public_key',
6
- public_key: Base64.encode64(Legion::Crypt.public_key),
7
- **Legion::Settings[:client] }
8
- Legion::Extensions::Node::Transport::Messages::PublicKey.new(message_hash).publish
9
- {}
10
- end
1
+ # frozen_string_literal: true
11
2
 
12
- def self.update_public_key(name:, public_key:, **_opts)
13
- log.debug 'update_public_key'
14
- Legion::Settings[:cluster][:public_keys][name] = public_key
15
- {}
16
- end
3
+ module Legion
4
+ module Extensions
5
+ module Node
6
+ module Runners
7
+ module Crypt
8
+ def push_public_key(**_opts)
9
+ log.debug 'push_public_key'
10
+ message_hash = { function: 'update_public_key',
11
+ public_key: Base64.encode64(Legion::Crypt.public_key),
12
+ **Legion::Settings[:client] }
13
+ Legion::Extensions::Node::Transport::Messages::PublicKey.new(message_hash).publish
14
+ {}
15
+ end
17
16
 
18
- def delete_public_key(name:, **_opts)
19
- log.debug 'delete_public_key'
20
- Legion::Settings[:cluster][:public_keys].delete(name)
21
- {}
22
- end
17
+ def self.update_public_key(name:, public_key:, **_opts)
18
+ log.debug 'update_public_key'
19
+ Legion::Settings[:cluster][:public_keys][name] = public_key
20
+ {}
21
+ end
23
22
 
24
- def request_public_keys(**_opts)
25
- log.debug 'request_public_keys'
26
- message_hash = { function: 'push_public_key' }
27
- Legion::Extensions::Node::Transport::Messages::RequestPublicKeys.new(**message_hash).publish
28
- {}
29
- end
23
+ def delete_public_key(name:, **_opts)
24
+ log.debug 'delete_public_key'
25
+ Legion::Settings[:cluster][:public_keys].delete(name)
26
+ {}
27
+ end
30
28
 
31
- def request_cluster_secret(**_opts)
32
- log.debug 'request_cluster_secret'
33
- Legion::Transport::Messages::RequestClusterSecret.new.publish
34
- {}
35
- end
29
+ def request_public_keys(**_opts)
30
+ log.debug 'request_public_keys'
31
+ message_hash = { function: 'push_public_key' }
32
+ Legion::Extensions::Node::Transport::Messages::RequestPublicKeys.new(**message_hash).publish
33
+ {}
34
+ end
36
35
 
37
- def push_cluster_secret(public_key:, queue_name:, **_opts)
38
- log.debug 'push_cluster_secret'
39
- return {} unless Legion::Settings[:crypt][:cs_encrypt_ready]
40
-
41
- encrypted = Legion::Crypt.encrypt_from_keypair(pub_key: public_key,
42
- message: Legion::Settings[:crypt][:cluster_secret].to_s)
43
- legion = Legion::Crypt.encrypt('legion')
44
- Legion::Extensions::Node::Transport::Messages::PushClusterSecret.new(message: encrypted,
45
- queue_name: queue_name,
46
- validation_string: 'legion',
47
- encrypted_string: legion).publish
48
- {}
49
- end
36
+ def request_cluster_secret(**_opts)
37
+ log.debug 'request_cluster_secret'
38
+ Legion::Transport::Messages::RequestClusterSecret.new.publish
39
+ {}
40
+ end
50
41
 
51
- def receive_cluster_secret(message:, **opts)
52
- log.debug 'receive_cluster_secret'
53
- Legion::Settings[:crypt][:cluster_secret] = Legion::Crypt.decrypt_from_keypair(message)
54
- Legion::Settings[:crypt][:encrypted_string] = opts[:encrypted_string]
55
- Legion::Settings[:crypt][:validation_string] = opts[:validation_string]
56
- {}
57
- end
42
+ def push_cluster_secret(public_key:, queue_name:, **_opts)
43
+ log.debug 'push_cluster_secret'
44
+ return {} unless Legion::Settings[:crypt][:cs_encrypt_ready]
45
+
46
+ encrypted = Legion::Crypt.encrypt_from_keypair(pub_key: public_key,
47
+ message: Legion::Settings[:crypt][:cluster_secret].to_s)
48
+ legion = Legion::Crypt.encrypt('legion')
49
+ Legion::Extensions::Node::Transport::Messages::PushClusterSecret.new(message: encrypted,
50
+ queue_name: queue_name,
51
+ validation_string: 'legion',
52
+ encrypted_string: legion).publish
53
+ {}
54
+ end
58
55
 
59
- include Legion::Extensions::Helpers::Lex
56
+ def receive_cluster_secret(message:, **opts)
57
+ log.debug 'receive_cluster_secret'
58
+ Legion::Settings[:crypt][:cluster_secret] = Legion::Crypt.decrypt_from_keypair(message)
59
+ Legion::Settings[:crypt][:encrypted_string] = opts[:encrypted_string]
60
+ Legion::Settings[:crypt][:validation_string] = opts[:validation_string]
61
+ {}
62
+ end
63
+
64
+ include Legion::Extensions::Helpers::Lex
65
+ end
66
+ end
67
+ end
60
68
  end
61
69
  end
@@ -1,61 +1,118 @@
1
- module Legion::Extensions::Node::Runners
2
- module Node
3
- def message(_options = {}, **hash)
4
- log.debug 'message'
5
- hash.each do |k, v|
6
- raise 'Cannot override base setting that doesn\'t exist' if Legion::Settings[k].nil?
7
-
8
- case v
9
- when String
10
- Legion::Settings[k] = v
11
- when Hash
12
- v.each do |key, value|
13
- Legion::Settings[k][key] = value
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module Node
6
+ module Runners
7
+ module Node
8
+ def message(_options = {}, **hash)
9
+ log.debug 'message'
10
+ hash.each do |k, v|
11
+ raise 'Cannot override base setting that doesn\'t exist' if Legion::Settings[k].nil?
12
+
13
+ case v
14
+ when String
15
+ Legion::Settings[k] = v
16
+ when Hash
17
+ v.each do |key, value|
18
+ Legion::Settings[k][key] = value
19
+ end
20
+ end
21
+ end
14
22
  end
15
- end
16
- end
17
- end
18
23
 
19
- def push_public_key(**_opts)
20
- log.debug 'push_public_key'
21
- message_hash = { function: 'update_public_key',
22
- public_key: Legion::Crypt.public_key.to_s,
23
- **Legion::Settings[:client] }
24
- Legion::Extensions::Node::Transport::Messages::PublicKey.new(**message_hash).publish
25
- {}
26
- end
24
+ def update_gem(extension:, version: nil, reload: true, **_opts)
25
+ name = extension.to_s.delete_prefix('lex-')
26
+ gem_name = "lex-#{name}"
27
+ log.debug "update_gem: installing #{gem_name} #{version || 'latest'}"
27
28
 
28
- def update_public_key(name:, public_key:, **_opts)
29
- log.debug 'update_public_key'
30
- Legion::Settings[:cluster][:public_keys][name] = public_key
31
- {}
32
- end
29
+ Gem.install(gem_name, version)
30
+ Legion.reload if reload
33
31
 
34
- def push_cluster_secret(public_key:, queue_name:, **_opts)
35
- log.debug 'push_cluster_secret'
36
- return {} unless Legion::Settings[:crypt][:cs_encrypt_ready]
37
-
38
- encrypted = Legion::Crypt.encrypt_from_keypair(pub_key: public_key,
39
- message: Legion::Settings[:crypt][:cluster_secret].to_s)
40
- legion = Legion::Crypt.encrypt('legion')
41
- Legion::Extensions::Node::Transport::Messages::PushClusterSecret.new(message: encrypted,
42
- queue_name: queue_name,
43
- validation_string: 'legion',
44
- encrypted_string: legion).publish
45
- {}
46
- end
32
+ publish_update_result(action: 'update_gem', status: 'success', detail: "#{gem_name} #{version || 'latest'}")
33
+ rescue StandardError => e
34
+ log.error "update_gem failed: #{e.message}"
35
+ publish_update_result(action: 'update_gem', status: 'failed', detail: gem_name, error: e.message)
36
+ end
47
37
 
48
- def receive_cluster_secret(message:, **_opts)
49
- log.debug 'receive_cluster_secret'
50
- Legion::Settings[:crypt][:cluster_secret] = Legion::Crypt.decrypt_from_keypair(message: message)
51
- {}
52
- end
38
+ def update_settings(settings:, restart: false, **_opts)
39
+ log.debug "update_settings: merging #{settings.keys.join(', ')}"
53
40
 
54
- def receive_vault_token(message:, routing_key:, public_key:, **)
55
- Legion::Extensions::Node::Runners::Vault.receive_vault_token(message: message, routing_key: routing_key,
56
- public_key: public_key)
57
- end
41
+ settings.each do |k, v|
42
+ case v
43
+ when Hash
44
+ Legion::Settings[k] ||= {}
45
+ v.each { |key, value| Legion::Settings[k][key] = value }
46
+ else
47
+ Legion::Settings[k] = v
48
+ end
49
+ end
50
+
51
+ Legion.reload if restart
52
+
53
+ publish_update_result(action: 'update_settings', status: 'success',
54
+ detail: "keys: #{settings.keys.join(', ')}")
55
+ rescue StandardError => e
56
+ log.error "update_settings failed: #{e.message}"
57
+ publish_update_result(action: 'update_settings', status: 'failed', error: e.message)
58
+ end
59
+
60
+ def push_public_key(**_opts)
61
+ log.debug 'push_public_key'
62
+ message_hash = { function: 'update_public_key',
63
+ public_key: Legion::Crypt.public_key.to_s,
64
+ **Legion::Settings[:client] }
65
+ Legion::Extensions::Node::Transport::Messages::PublicKey.new(**message_hash).publish
66
+ {}
67
+ end
58
68
 
59
- include Legion::Extensions::Helpers::Lex
69
+ def update_public_key(name:, public_key:, **_opts)
70
+ log.debug 'update_public_key'
71
+ Legion::Settings[:cluster][:public_keys][name] = public_key
72
+ {}
73
+ end
74
+
75
+ def push_cluster_secret(public_key:, queue_name:, **_opts)
76
+ log.debug 'push_cluster_secret'
77
+ return {} unless Legion::Settings[:crypt][:cs_encrypt_ready]
78
+
79
+ encrypted = Legion::Crypt.encrypt_from_keypair(pub_key: public_key,
80
+ message: Legion::Settings[:crypt][:cluster_secret].to_s)
81
+ legion = Legion::Crypt.encrypt('legion')
82
+ Legion::Extensions::Node::Transport::Messages::PushClusterSecret.new(message: encrypted,
83
+ queue_name: queue_name,
84
+ validation_string: 'legion',
85
+ encrypted_string: legion).publish
86
+ {}
87
+ end
88
+
89
+ def receive_cluster_secret(message:, **_opts)
90
+ log.debug 'receive_cluster_secret'
91
+ Legion::Settings[:crypt][:cluster_secret] = Legion::Crypt.decrypt_from_keypair(message: message)
92
+ {}
93
+ end
94
+
95
+ def receive_vault_token(message:, routing_key:, public_key:, **)
96
+ Legion::Extensions::Node::Runners::Vault.receive_vault_token(message: message, routing_key: routing_key,
97
+ public_key: public_key)
98
+ end
99
+
100
+ private
101
+
102
+ def publish_update_result(action:, status:, detail: nil, error: nil)
103
+ Legion::Extensions::Node::Transport::Messages::UpdateResult.new(
104
+ action: action,
105
+ status: status,
106
+ detail: detail,
107
+ error: error,
108
+ node: Legion::Settings[:client][:name],
109
+ timestamp: Time.now.utc.iso8601
110
+ ).publish
111
+ end
112
+
113
+ include Legion::Extensions::Helpers::Lex
114
+ end
115
+ end
116
+ end
60
117
  end
61
118
  end
@@ -1,40 +1,48 @@
1
- module Legion::Extensions::Node::Runners
2
- module Vault
3
- def request_token(**)
4
- return {} if Legion::Settings[:crypt][:vault][:connected]
5
- return {} unless Legion::Settings[:crypt][:vault][:enabled]
6
-
7
- request_vault_token
8
- end
9
-
10
- def request_vault_token(**)
11
- Legion::Extensions::Node::Transport::Messages::RequestVaultToken.new.publish
12
- {}
13
- end
14
-
15
- def receive_vault_token(message:, **opts) # rubocop:disable Metrics/AbcSize
16
- return if Legion::Settings[:crypt][:vault][:connected]
17
-
18
- Legion::Settings[:crypt][:vault][:token] = Legion::Crypt.decrypt_from_keypair(message: message)
19
- %i[protocol address port].each do |setting|
20
- next unless opts.key? setting
21
- next unless Legion::Settings[:crypt][:vault][setting].nil?
22
-
23
- Legion::Settings[:crypt][:vault][setting] = opts[setting]
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module Node
6
+ module Runners
7
+ module Vault
8
+ def request_token(**)
9
+ return {} if Legion::Settings[:crypt][:vault][:connected]
10
+ return {} unless Legion::Settings[:crypt][:vault][:enabled]
11
+
12
+ request_vault_token
13
+ end
14
+
15
+ def request_vault_token(**)
16
+ Legion::Extensions::Node::Transport::Messages::RequestVaultToken.new.publish
17
+ {}
18
+ end
19
+
20
+ def receive_vault_token(message:, **opts)
21
+ return if Legion::Settings[:crypt][:vault][:connected]
22
+
23
+ Legion::Settings[:crypt][:vault][:token] = Legion::Crypt.decrypt_from_keypair(message: message)
24
+ %i[protocol address port].each do |setting|
25
+ next unless opts.key? setting
26
+ next unless Legion::Settings[:crypt][:vault][setting].nil?
27
+
28
+ Legion::Settings[:crypt][:vault][setting] = opts[setting]
29
+ end
30
+ Legion::Crypt.connect_vault
31
+ {}
32
+ end
33
+
34
+ def push_vault_token(public_key:, node_name:, **)
35
+ return {} unless Legion::Settings[:crypt][:vault][:token]
36
+
37
+ encrypted = Legion::Crypt.encrypt_from_keypair(message: Legion::Settings[:crypt][:vault][:token],
38
+ pub_key: public_key)
39
+ Legion::Extensions::Node::Transport::Messages::PushVaultToken.new(token: encrypted, queue_name: node_name).publish
40
+ {}
41
+ end
42
+
43
+ include Legion::Extensions::Helpers::Lex
44
+ end
24
45
  end
25
- Legion::Crypt.connect_vault
26
- {}
27
46
  end
28
-
29
- def push_vault_token(public_key:, node_name:, **)
30
- return {} unless Legion::Settings[:crypt][:vault][:token]
31
-
32
- encrypted = Legion::Crypt.encrypt_from_keypair(message: Legion::Settings[:crypt][:vault][:token],
33
- pub_key: public_key)
34
- Legion::Extensions::Node::Transport::Messages::PushVaultToken.new(token: encrypted, queue_name: node_name).publish
35
- {}
36
- end
37
-
38
- include Legion::Extensions::Helpers::Lex
39
47
  end
40
48
  end
@@ -1,11 +1,17 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'legion/transport/exchanges/node'
2
4
 
3
- module Legion::Extensions::Node
4
- module Transport
5
- module Exchanges
6
- class Node < Legion::Transport::Exchanges::Node
7
- def exchange_name
8
- 'node'
5
+ module Legion
6
+ module Extensions
7
+ module Node
8
+ module Transport
9
+ module Exchanges
10
+ class Node < Legion::Transport::Exchanges::Node
11
+ def exchange_name
12
+ 'node'
13
+ end
14
+ end
9
15
  end
10
16
  end
11
17
  end
@@ -1,31 +1,94 @@
1
- module Legion::Extensions::Node::Transport::Messages
2
- class Beat < Legion::Transport::Message
3
- def routing_key
4
- 'status'
5
- end
1
+ # frozen_string_literal: true
6
2
 
7
- def type
8
- 'heartbeat'
9
- end
3
+ module Legion
4
+ module Extensions
5
+ module Node
6
+ module Transport
7
+ module Messages
8
+ class Beat < Legion::Transport::Message
9
+ def routing_key
10
+ 'status'
11
+ end
10
12
 
11
- def expiration
12
- 5000
13
- end
13
+ def type
14
+ 'heartbeat'
15
+ end
14
16
 
15
- def encrypt?
16
- false
17
- end
17
+ def expiration
18
+ 5000
19
+ end
18
20
 
19
- def message
20
- hash = { name: Legion::Settings[:client][:hostname], pid: Process.pid, timestamp: Time.now }
21
- hash[:status] = @options[:status].nil? ? 'healthy' : @options[:status]
22
- hash
23
- end
21
+ def encrypt?
22
+ false
23
+ end
24
+
25
+ def message
26
+ hash = {
27
+ name: Legion::Settings[:client][:hostname],
28
+ pid: ::Process.pid,
29
+ timestamp: Time.now,
30
+ status: @options[:status].nil? ? 'healthy' : @options[:status]
31
+ }
32
+ hash[:version] = Legion::VERSION if defined?(Legion::VERSION)
33
+ hash[:metrics] = collect_metrics
34
+ hash[:hosted_worker_ids] = collect_worker_ids
35
+ hash
36
+ end
37
+
38
+ def validate
39
+ raise 'status should be a string' unless @options[:status].is_a?(String) || @options[:status].nil?
40
+
41
+ @valid = true
42
+ end
43
+
44
+ private
45
+
46
+ def collect_metrics
47
+ times = ::Process.times
48
+ {
49
+ memory_rss_mb: rss_mb,
50
+ cpu_user_seconds: times.utime.round(2),
51
+ cpu_system_seconds: times.stime.round(2),
52
+ thread_count: Thread.list.count,
53
+ loaded_extensions: loaded_extension_count,
54
+ uptime_seconds: uptime_seconds
55
+ }
56
+ end
57
+
58
+ def rss_mb
59
+ if RUBY_PLATFORM.include?('darwin')
60
+ `ps -o rss= -p #{::Process.pid}`.strip.to_i / 1024.0
61
+ else
62
+ File.read("/proc/#{::Process.pid}/statm").split[1].to_i * (4096.0 / 1_048_576)
63
+ end
64
+ rescue StandardError
65
+ 0.0
66
+ end
67
+
68
+ def loaded_extension_count
69
+ return 0 unless defined?(Legion::Extensions)
70
+
71
+ Legion::Extensions.respond_to?(:loaded_extensions) ? Legion::Extensions.loaded_extensions.count : 0
72
+ end
73
+
74
+ def uptime_seconds
75
+ (::Process.clock_gettime(::Process::CLOCK_MONOTONIC) - boot_time).round(0)
76
+ end
77
+
78
+ def boot_time
79
+ @boot_time ||= ::Process.clock_gettime(::Process::CLOCK_MONOTONIC)
80
+ end
24
81
 
25
- def validate
26
- raise 'status should be a string' unless @options[:status].is_a?(String) || @options[:status].nil?
82
+ def collect_worker_ids
83
+ return [] unless defined?(Legion::DigitalWorker)
27
84
 
28
- @valid = true
85
+ Legion::DigitalWorker.active_local_ids
86
+ rescue StandardError
87
+ []
88
+ end
89
+ end
90
+ end
91
+ end
29
92
  end
30
93
  end
31
94
  end