lex-health 0.1.7 → 0.2.0
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/.gitignore +2 -0
- data/CHANGELOG.md +19 -0
- data/CLAUDE.md +1 -1
- data/lib/legion/extensions/health/runners/health.rb +16 -6
- data/lib/legion/extensions/health/runners/watchdog.rb +3 -1
- data/lib/legion/extensions/health/transport/messages/watchdog.rb +1 -1
- data/lib/legion/extensions/health/version.rb +1 -1
- data/lib/legion/extensions/health.rb +0 -4
- metadata +1 -3
- data/.circleci/config.yml +0 -61
- data/Gemfile.lock +0 -86
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 51bae536ed975da049ebfa332b71974b49d85886afed5f7c631de9c9d7c63265
|
|
4
|
+
data.tar.gz: 9e24916e2b2d9229121c89884c7487453dd569b24ae2fb4c277dce33a615d4d5
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a38f069ff4658cc951d1b4615e319daaf7e1576a285c37d4b8f3e40649caca8ce1e94e2d447a89be955d49e51238b26c3cab0b516d61caa43701eb61243c4a98
|
|
7
|
+
data.tar.gz: e31fd840329ca93fef39026b29dd786a3e12ebd980b8aad64332d6ad30c4bde8d9be66ead9f530416f39719a9de9150646bbc49922efce43d38b6a217a3e1ab2
|
data/.gitignore
CHANGED
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.2.0] - 2026-03-18
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
- `active` column now uses boolean `true` instead of integer `1` (PostgreSQL compatibility)
|
|
7
|
+
- Watchdog message routing key changed from `'health'` to `'node.health'` to match queue binding
|
|
8
|
+
- Added `require 'time'` for `Time.parse`
|
|
9
|
+
- Nil guard on `updated` timestamp in back-in-time comparison
|
|
10
|
+
- TOCTOU race condition on concurrent heartbeat inserts (rescue UniqueConstraintViolation)
|
|
11
|
+
- `delete` method nil guard for nonexistent nodes
|
|
12
|
+
- `mark_workers_offline` now clears `health_node` on expired workers
|
|
13
|
+
|
|
14
|
+
### Changed
|
|
15
|
+
- Entry point `data_required?` is now `self.` (class method) matching framework expectation
|
|
16
|
+
|
|
17
|
+
## [0.1.8] - 2026-03-17
|
|
18
|
+
|
|
19
|
+
### Fixed
|
|
20
|
+
- Watchdog `expire` guards against missing `Legion::Data::Model::Node` constant before use, returning an error hash when the model is unavailable
|
|
21
|
+
|
|
3
22
|
## [0.1.7] - 2026-03-16
|
|
4
23
|
|
|
5
24
|
### Fixed
|
data/CLAUDE.md
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require 'time'
|
|
4
|
+
|
|
3
5
|
module Legion
|
|
4
6
|
module Extensions
|
|
5
7
|
module Health
|
|
@@ -16,7 +18,7 @@ module Legion
|
|
|
16
18
|
return { success: result, hostname: hostname, **opts }
|
|
17
19
|
end
|
|
18
20
|
|
|
19
|
-
if opts.key?(:timestamp) &&
|
|
21
|
+
if opts.key?(:timestamp) && item.values[:updated] && item.values[:updated] > Time.parse(opts[:timestamp])
|
|
20
22
|
return { success: false,
|
|
21
23
|
reason: 'entry already updated',
|
|
22
24
|
hostname: hostname,
|
|
@@ -24,7 +26,7 @@ module Legion
|
|
|
24
26
|
**opts }
|
|
25
27
|
end
|
|
26
28
|
|
|
27
|
-
update_hash = { active:
|
|
29
|
+
update_hash = { active: true, status: opts[:status], name: hostname, updated: Sequel::CURRENT_TIMESTAMP }
|
|
28
30
|
update_hash[:metrics] = Legion::JSON.dump(opts[:metrics]) if opts[:metrics]
|
|
29
31
|
update_hash[:hosted_worker_ids] = Legion::JSON.dump(opts[:hosted_worker_ids]) if opts[:hosted_worker_ids]
|
|
30
32
|
update_hash[:version] = opts[:version] if opts[:version]
|
|
@@ -36,19 +38,27 @@ module Legion
|
|
|
36
38
|
end
|
|
37
39
|
|
|
38
40
|
def insert(hostname:, status: 'unknown', **opts)
|
|
39
|
-
insert = { active:
|
|
41
|
+
insert = { active: true, status: status, name: hostname }
|
|
40
42
|
insert[:datacenter_id] = opts[:datacenter_id] if opts.key? :datacenter_id
|
|
41
43
|
insert[:environment_id] = opts[:environment_id] if opts.key? :environment_id
|
|
42
|
-
insert[:active] = opts[:active] if opts.key? :active
|
|
43
44
|
insert[:metrics] = Legion::JSON.dump(opts[:metrics]) if opts[:metrics]
|
|
44
45
|
insert[:hosted_worker_ids] = Legion::JSON.dump(opts[:hosted_worker_ids]) if opts[:hosted_worker_ids]
|
|
45
46
|
insert[:version] = opts[:version] if opts[:version]
|
|
46
47
|
|
|
47
|
-
|
|
48
|
+
node_id = begin
|
|
49
|
+
Legion::Data::Model::Node.insert(insert)
|
|
50
|
+
rescue Sequel::UniqueConstraintViolation
|
|
51
|
+
item = Legion::Data::Model::Node[name: hostname]
|
|
52
|
+
item&.id
|
|
53
|
+
end
|
|
54
|
+
{ success: true, hostname: hostname, node_id: node_id, **insert }
|
|
48
55
|
end
|
|
49
56
|
|
|
50
57
|
def delete(node_id:, **_opts)
|
|
51
|
-
Legion::Data::Model::Node[node_id]
|
|
58
|
+
node = Legion::Data::Model::Node[node_id]
|
|
59
|
+
return { success: false, error: 'node not found', node_id: node_id } if node.nil?
|
|
60
|
+
|
|
61
|
+
node.delete
|
|
52
62
|
{ success: true, node_id: node_id }
|
|
53
63
|
end
|
|
54
64
|
|
|
@@ -8,6 +8,8 @@ module Legion
|
|
|
8
8
|
include Legion::Extensions::Helpers::Lex
|
|
9
9
|
|
|
10
10
|
def expire(expire_time: 60, **_opts)
|
|
11
|
+
return { success: false, reason: 'Legion::Data::Model::Node not available' } unless defined?(Legion::Data::Model::Node)
|
|
12
|
+
|
|
11
13
|
cutoff = Time.now - expire_time
|
|
12
14
|
nodes = []
|
|
13
15
|
Legion::Data::Model::Node
|
|
@@ -36,7 +38,7 @@ module Legion
|
|
|
36
38
|
Legion::Data::Model::DigitalWorker
|
|
37
39
|
.where(health_node: node_name, health_status: 'online')
|
|
38
40
|
.each do |worker|
|
|
39
|
-
worker.update(health_status: 'offline')
|
|
41
|
+
worker.update(health_status: 'offline', health_node: nil)
|
|
40
42
|
end
|
|
41
43
|
rescue StandardError => e
|
|
42
44
|
log.warn "worker offline marking failed: #{e.message}" if respond_to?(:log)
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: lex-health
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Esity
|
|
@@ -100,7 +100,6 @@ executables: []
|
|
|
100
100
|
extensions: []
|
|
101
101
|
extra_rdoc_files: []
|
|
102
102
|
files:
|
|
103
|
-
- ".circleci/config.yml"
|
|
104
103
|
- ".github/workflows/ci.yml"
|
|
105
104
|
- ".gitignore"
|
|
106
105
|
- ".rspec"
|
|
@@ -109,7 +108,6 @@ files:
|
|
|
109
108
|
- CLAUDE.md
|
|
110
109
|
- Dockerfile
|
|
111
110
|
- Gemfile
|
|
112
|
-
- Gemfile.lock
|
|
113
111
|
- LICENSE.txt
|
|
114
112
|
- README.md
|
|
115
113
|
- Rakefile
|
data/.circleci/config.yml
DELETED
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
version: 2.1
|
|
2
|
-
orbs:
|
|
3
|
-
ruby: circleci/ruby@0.2.1
|
|
4
|
-
|
|
5
|
-
jobs:
|
|
6
|
-
"rubocop":
|
|
7
|
-
docker:
|
|
8
|
-
- image: circleci/ruby:2.5-node
|
|
9
|
-
steps:
|
|
10
|
-
- checkout
|
|
11
|
-
- ruby/load-cache
|
|
12
|
-
- ruby/install-deps
|
|
13
|
-
- run:
|
|
14
|
-
name: Run Rubocop
|
|
15
|
-
command: bundle exec rubocop
|
|
16
|
-
- ruby/save-cache
|
|
17
|
-
"ruby-two-five":
|
|
18
|
-
docker:
|
|
19
|
-
- image: circleci/ruby:2.5
|
|
20
|
-
- image: memcached:1.5-alpine
|
|
21
|
-
steps:
|
|
22
|
-
- checkout
|
|
23
|
-
- ruby/load-cache
|
|
24
|
-
- ruby/install-deps
|
|
25
|
-
- ruby/run-tests
|
|
26
|
-
- ruby/save-cache
|
|
27
|
-
"ruby-two-six":
|
|
28
|
-
docker:
|
|
29
|
-
- image: circleci/ruby:2.6
|
|
30
|
-
- image: memcached:1.5-alpine
|
|
31
|
-
steps:
|
|
32
|
-
- checkout
|
|
33
|
-
- ruby/load-cache
|
|
34
|
-
- ruby/install-deps
|
|
35
|
-
- ruby/run-tests
|
|
36
|
-
- ruby/save-cache
|
|
37
|
-
"ruby-two-seven":
|
|
38
|
-
docker:
|
|
39
|
-
- image: circleci/ruby:2.7
|
|
40
|
-
- image: memcached:1.5-alpine
|
|
41
|
-
steps:
|
|
42
|
-
- checkout
|
|
43
|
-
- ruby/load-cache
|
|
44
|
-
- ruby/install-deps
|
|
45
|
-
- ruby/run-tests
|
|
46
|
-
- ruby/save-cache
|
|
47
|
-
|
|
48
|
-
workflows:
|
|
49
|
-
version: 2
|
|
50
|
-
rubocop-rspec:
|
|
51
|
-
jobs:
|
|
52
|
-
- rubocop
|
|
53
|
-
- ruby-two-five:
|
|
54
|
-
requires:
|
|
55
|
-
- rubocop
|
|
56
|
-
- ruby-two-six:
|
|
57
|
-
requires:
|
|
58
|
-
- ruby-two-five
|
|
59
|
-
- ruby-two-seven:
|
|
60
|
-
requires:
|
|
61
|
-
- ruby-two-five
|
data/Gemfile.lock
DELETED
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
PATH
|
|
2
|
-
remote: .
|
|
3
|
-
specs:
|
|
4
|
-
lex-health (0.1.7)
|
|
5
|
-
|
|
6
|
-
GEM
|
|
7
|
-
remote: https://rubygems.org/
|
|
8
|
-
specs:
|
|
9
|
-
addressable (2.8.9)
|
|
10
|
-
public_suffix (>= 2.0.2, < 8.0)
|
|
11
|
-
ast (2.4.3)
|
|
12
|
-
bigdecimal (4.0.1)
|
|
13
|
-
diff-lcs (1.6.2)
|
|
14
|
-
json (2.19.1)
|
|
15
|
-
json-schema (6.2.0)
|
|
16
|
-
addressable (~> 2.8)
|
|
17
|
-
bigdecimal (>= 3.1, < 5)
|
|
18
|
-
language_server-protocol (3.17.0.5)
|
|
19
|
-
lint_roller (1.1.0)
|
|
20
|
-
mcp (0.8.0)
|
|
21
|
-
json-schema (>= 4.1)
|
|
22
|
-
parallel (1.27.0)
|
|
23
|
-
parser (3.3.10.2)
|
|
24
|
-
ast (~> 2.4.1)
|
|
25
|
-
racc
|
|
26
|
-
prism (1.9.0)
|
|
27
|
-
public_suffix (7.0.5)
|
|
28
|
-
racc (1.8.1)
|
|
29
|
-
rainbow (3.1.1)
|
|
30
|
-
rake (13.3.1)
|
|
31
|
-
regexp_parser (2.11.3)
|
|
32
|
-
rspec (3.13.2)
|
|
33
|
-
rspec-core (~> 3.13.0)
|
|
34
|
-
rspec-expectations (~> 3.13.0)
|
|
35
|
-
rspec-mocks (~> 3.13.0)
|
|
36
|
-
rspec-core (3.13.6)
|
|
37
|
-
rspec-support (~> 3.13.0)
|
|
38
|
-
rspec-expectations (3.13.5)
|
|
39
|
-
diff-lcs (>= 1.2.0, < 2.0)
|
|
40
|
-
rspec-support (~> 3.13.0)
|
|
41
|
-
rspec-mocks (3.13.8)
|
|
42
|
-
diff-lcs (>= 1.2.0, < 2.0)
|
|
43
|
-
rspec-support (~> 3.13.0)
|
|
44
|
-
rspec-support (3.13.7)
|
|
45
|
-
rubocop (1.85.1)
|
|
46
|
-
json (~> 2.3)
|
|
47
|
-
language_server-protocol (~> 3.17.0.2)
|
|
48
|
-
lint_roller (~> 1.1.0)
|
|
49
|
-
mcp (~> 0.6)
|
|
50
|
-
parallel (~> 1.10)
|
|
51
|
-
parser (>= 3.3.0.2)
|
|
52
|
-
rainbow (>= 2.2.2, < 4.0)
|
|
53
|
-
regexp_parser (>= 2.9.3, < 3.0)
|
|
54
|
-
rubocop-ast (>= 1.49.0, < 2.0)
|
|
55
|
-
ruby-progressbar (~> 1.7)
|
|
56
|
-
unicode-display_width (>= 2.4.0, < 4.0)
|
|
57
|
-
rubocop-ast (1.49.1)
|
|
58
|
-
parser (>= 3.3.7.2)
|
|
59
|
-
prism (~> 1.7)
|
|
60
|
-
rubocop-rspec (3.9.0)
|
|
61
|
-
lint_roller (~> 1.1)
|
|
62
|
-
rubocop (~> 1.81)
|
|
63
|
-
ruby-progressbar (1.13.0)
|
|
64
|
-
sequel (5.102.0)
|
|
65
|
-
bigdecimal
|
|
66
|
-
sqlite3 (2.9.2-arm64-darwin)
|
|
67
|
-
sqlite3 (2.9.2-x86_64-linux-gnu)
|
|
68
|
-
unicode-display_width (3.2.0)
|
|
69
|
-
unicode-emoji (~> 4.1)
|
|
70
|
-
unicode-emoji (4.2.0)
|
|
71
|
-
|
|
72
|
-
PLATFORMS
|
|
73
|
-
arm64-darwin-25
|
|
74
|
-
x86_64-linux
|
|
75
|
-
|
|
76
|
-
DEPENDENCIES
|
|
77
|
-
lex-health!
|
|
78
|
-
rake
|
|
79
|
-
rspec
|
|
80
|
-
rubocop
|
|
81
|
-
rubocop-rspec
|
|
82
|
-
sequel
|
|
83
|
-
sqlite3
|
|
84
|
-
|
|
85
|
-
BUNDLED WITH
|
|
86
|
-
2.6.9
|