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.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +16 -0
- data/.rubocop.yml +40 -10
- data/CHANGELOG.md +19 -0
- data/CLAUDE.md +109 -0
- data/Dockerfile +1 -1
- data/Gemfile +2 -0
- data/Gemfile.lock +87 -0
- data/README.md +65 -5
- data/docker_deploy.rb +1 -0
- data/lex-node.gemspec +4 -1
- data/lib/legion/extensions/node/actors/beat.rb +27 -19
- data/lib/legion/extensions/node/actors/crypt.rb +12 -4
- data/lib/legion/extensions/node/actors/push_key.rb +27 -19
- data/lib/legion/extensions/node/actors/vault.rb +27 -19
- data/lib/legion/extensions/node/actors/vault_token_request.rb +27 -19
- data/lib/legion/extensions/node/data_test/migrations/001_nodes_table.rb +2 -0
- data/lib/legion/extensions/node/data_test/migrations/002_node_history_table.rb +2 -1
- data/lib/legion/extensions/node/data_test/migrations/003_legion_version_colume.rb +2 -0
- data/lib/legion/extensions/node/data_test/migrations/004_node_extensions.rb +2 -1
- data/lib/legion/extensions/node/runners/beat.rb +17 -9
- data/lib/legion/extensions/node/runners/crypt.rb +60 -52
- data/lib/legion/extensions/node/runners/node.rb +109 -52
- data/lib/legion/extensions/node/runners/vault.rb +44 -36
- data/lib/legion/extensions/node/transport/exchanges/node.rb +12 -6
- data/lib/legion/extensions/node/transport/messages/beat.rb +85 -22
- data/lib/legion/extensions/node/transport/messages/public_key.rb +24 -14
- data/lib/legion/extensions/node/transport/messages/push_cluster_secret.rb +34 -24
- data/lib/legion/extensions/node/transport/messages/push_vault_token.rb +34 -24
- data/lib/legion/extensions/node/transport/messages/request_cluster_secret.rb +26 -16
- data/lib/legion/extensions/node/transport/messages/request_public_keys.rb +23 -13
- data/lib/legion/extensions/node/transport/messages/request_vault_token.rb +31 -21
- data/lib/legion/extensions/node/transport/messages/update_result.rb +36 -0
- data/lib/legion/extensions/node/transport/queues/crypt.rb +14 -4
- data/lib/legion/extensions/node/transport/queues/health.rb +14 -4
- data/lib/legion/extensions/node/transport/queues/node.rb +18 -7
- data/lib/legion/extensions/node/transport/queues/vault.rb +14 -4
- data/lib/legion/extensions/node/transport.rb +17 -8
- data/lib/legion/extensions/node/version.rb +3 -1
- data/lib/legion/extensions/node.rb +2 -0
- metadata +10 -9
- data/.github/workflows/rspec.yml +0 -69
- data/.github/workflows/rubocop.yml +0 -28
|
@@ -1,27 +1,35 @@
|
|
|
1
|
-
|
|
2
|
-
class VaultTokenRequest < Legion::Extensions::Actors::Once
|
|
3
|
-
def runner_function
|
|
4
|
-
'request_token'
|
|
5
|
-
end
|
|
1
|
+
# frozen_string_literal: true
|
|
6
2
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
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
|
-
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
def runner_class
|
|
13
|
+
Legion::Extensions::Node::Runners::Vault
|
|
14
|
+
end
|
|
14
15
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
def use_runner?
|
|
17
|
+
false
|
|
18
|
+
end
|
|
18
19
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
def check_subtask?
|
|
21
|
+
false
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def generate_task?
|
|
25
|
+
false
|
|
26
|
+
end
|
|
22
27
|
|
|
23
|
-
|
|
24
|
-
|
|
28
|
+
def delay
|
|
29
|
+
0
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
25
33
|
end
|
|
26
34
|
end
|
|
27
35
|
end
|
|
@@ -1,13 +1,21 @@
|
|
|
1
|
-
|
|
2
|
-
module Beat
|
|
3
|
-
include Legion::Extensions::Helpers::Transport
|
|
1
|
+
# frozen_string_literal: true
|
|
4
2
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
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
|
-
|
|
16
|
+
include Legion::Extensions::Helpers::Lex
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
12
20
|
end
|
|
13
21
|
end
|
|
@@ -1,61 +1,69 @@
|
|
|
1
|
-
|
|
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
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
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
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
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
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
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
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
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
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
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
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
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
|
-
|
|
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
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
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
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
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
|
-
|
|
29
|
-
|
|
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
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
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
|
-
|
|
49
|
-
|
|
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
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
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
|
-
|
|
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
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
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
|
|
4
|
-
module
|
|
5
|
-
module
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
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
|
-
|
|
2
|
-
class Beat < Legion::Transport::Message
|
|
3
|
-
def routing_key
|
|
4
|
-
'status'
|
|
5
|
-
end
|
|
1
|
+
# frozen_string_literal: true
|
|
6
2
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
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
|
-
|
|
12
|
-
|
|
13
|
-
|
|
13
|
+
def type
|
|
14
|
+
'heartbeat'
|
|
15
|
+
end
|
|
14
16
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
17
|
+
def expiration
|
|
18
|
+
5000
|
|
19
|
+
end
|
|
18
20
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
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
|
-
|
|
26
|
-
|
|
82
|
+
def collect_worker_ids
|
|
83
|
+
return [] unless defined?(Legion::DigitalWorker)
|
|
27
84
|
|
|
28
|
-
|
|
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
|