solid_queue_guard 1.2.5 → 1.3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1893e95d5ab5c66e556b93b743f0a981b62509716b11350b546941af696cf282
4
- data.tar.gz: 44d23bf1b5f8900a50c84446a2abaaba97bba4689979d5f0799d148e7edee06d
3
+ metadata.gz: d67d9fdbc9de83d8566bfc3c7529e4be2bf3e924cba7f840b555869cd0b2a618
4
+ data.tar.gz: 63368e74ee06a570c18d7f7cd7ea56de72355ae84327f883a01233f1bee38cd5
5
5
  SHA512:
6
- metadata.gz: 3a90a43b4541edd2f96ad9795708a016934ac6820998c83c4217be5902c8210fdf8ba0bb07ba021922cc297f58caf23a704640231fc6f65b28842d32e9bb3e79
7
- data.tar.gz: 50df8d5b56540152da201bf0a71acd9cb9f8d1ae9a11b180d66f5d597e274982c54bb16bec3d82d5cc1997cd12c7fa128db983a1a10e303c4e93cc47e8b9a954
6
+ metadata.gz: 20bfa32ec7ae3b150414576877e57f432364f21df151082e6fd4a6d7da7c9b3802899223fcc33b37dc529b2ecf3a4723748b4a9ec30b5bd32fa168632cf73840
7
+ data.tar.gz: 4b1553424fb1ad718edd40f22f06cf463837fc82bcb7350efd4c062b956cfd94a7cffdeb329460afbb23f17f40f0e30243b169c314c49f8679c41ed67ea89346
data/CHANGELOG.md CHANGED
@@ -5,6 +5,18 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [1.3.0] - 2026-07-29
9
+
10
+ ### Changed
11
+
12
+ - `process_heartbeat_config` no longer warns just because `process_heartbeat_interval` and
13
+ `process_alive_threshold` keep the Solid Queue defaults — the defaults now pass. The check
14
+ validates the relationship between the values instead: it fails when `process_alive_threshold`
15
+ is not above the heartbeat interval, and warns when the margin tolerates less than
16
+ `min_margin` heartbeats (default 2) or when Guard's `stale_process_threshold` is above
17
+ `process_alive_threshold`
18
+ - `config.checks.process_heartbeat_config = { min_margin: 3 }` tunes the required margin
19
+
8
20
  ## [1.2.5] - 2026-07-10
9
21
 
10
22
  ### Fixed
@@ -3,26 +3,107 @@
3
3
  module SolidQueueGuard
4
4
  module Checks
5
5
  module Config
6
+ # Solid Queue prunes any process whose heartbeat is older than
7
+ # process_alive_threshold, releasing the executions it had claimed. A live
8
+ # worker that merely delayed a heartbeat is pruned the same way, so the
9
+ # threshold must leave room for more than one missed beat.
6
10
  class ProcessHeartbeatConfigCheck < Base
7
- DEFAULT_HEARTBEAT_INTERVAL = 60.seconds
8
- DEFAULT_ALIVE_THRESHOLD = 5.minutes
11
+ DEFAULT_MIN_MARGIN = 2
9
12
 
10
13
  def call
11
- heartbeat_interval = SolidQueue.process_heartbeat_interval
12
- alive_threshold = SolidQueue.process_alive_threshold
13
-
14
- if heartbeat_interval == DEFAULT_HEARTBEAT_INTERVAL && alive_threshold == DEFAULT_ALIVE_THRESHOLD
15
- warn(
16
- 'process_heartbeat_config',
17
- 'Process heartbeat thresholds use defaults (interval: 60s, alive: 5m)',
18
- suggestion: 'Consider customizing process_alive_threshold for your deployment latency requirements'
19
- )
20
- else
21
- pass(
22
- 'process_heartbeat_config',
23
- "Process heartbeat interval: #{heartbeat_interval.inspect}, alive threshold: #{alive_threshold.inspect}"
24
- )
25
- end
14
+ return invalid_heartbeat_interval unless heartbeat_interval.positive?
15
+ return alive_threshold_too_low if alive_threshold <= heartbeat_interval
16
+ return margin_too_tight if margin < min_margin
17
+ return guard_threshold_above_alive if stale_process_threshold > alive_threshold
18
+
19
+ healthy_thresholds
20
+ end
21
+
22
+ private
23
+
24
+ def healthy_thresholds
25
+ pass(
26
+ check_id,
27
+ "Heartbeat interval: #{humanize(heartbeat_interval)}, " \
28
+ "alive threshold: #{humanize(alive_threshold)} (#{margin.round(1)}x margin)",
29
+ metadata: base_metadata
30
+ )
31
+ end
32
+
33
+ def invalid_heartbeat_interval
34
+ failure(
35
+ check_id,
36
+ 'process_heartbeat_interval must be a positive duration',
37
+ suggestion: 'Set SolidQueue.process_heartbeat_interval to a positive value (default: 60 seconds)',
38
+ metadata: base_metadata
39
+ )
40
+ end
41
+
42
+ def alive_threshold_too_low
43
+ failure(
44
+ check_id,
45
+ "process_alive_threshold (#{humanize(alive_threshold)}) is not greater than " \
46
+ "process_heartbeat_interval (#{humanize(heartbeat_interval)})",
47
+ suggestion: "Raise process_alive_threshold to at least #{humanize(recommended_threshold)} " \
48
+ 'so a single late heartbeat does not prune a live process',
49
+ metadata: base_metadata
50
+ )
51
+ end
52
+
53
+ def margin_too_tight
54
+ warn(
55
+ check_id,
56
+ "process_alive_threshold (#{humanize(alive_threshold)}) tolerates less than " \
57
+ "#{min_margin} heartbeats of #{humanize(heartbeat_interval)}",
58
+ suggestion: "Raise process_alive_threshold to at least #{humanize(recommended_threshold)} " \
59
+ 'so a single late heartbeat does not release claimed jobs',
60
+ metadata: base_metadata
61
+ )
62
+ end
63
+
64
+ def guard_threshold_above_alive
65
+ warn(
66
+ check_id,
67
+ "Guard stale_process_threshold (#{humanize(stale_process_threshold)}) is above " \
68
+ "process_alive_threshold (#{humanize(alive_threshold)})",
69
+ suggestion: "Lower stale_process_threshold to at most #{humanize(alive_threshold)}; " \
70
+ 'Solid Queue prunes dead process rows before Guard would report them as stale',
71
+ metadata: base_metadata.merge(stale_process_threshold: stale_process_threshold)
72
+ )
73
+ end
74
+
75
+ def heartbeat_interval
76
+ @heartbeat_interval ||= SolidQueue.process_heartbeat_interval.to_i
77
+ end
78
+
79
+ def alive_threshold
80
+ @alive_threshold ||= SolidQueue.process_alive_threshold.to_i
81
+ end
82
+
83
+ def stale_process_threshold
84
+ @stale_process_threshold ||= guard_config.check_setting(
85
+ :stale_process, :threshold, guard_config.stale_process_threshold
86
+ ).to_i
87
+ end
88
+
89
+ def min_margin
90
+ @min_margin ||= check_setting(:min_margin, DEFAULT_MIN_MARGIN)
91
+ end
92
+
93
+ def margin
94
+ @margin ||= alive_threshold / heartbeat_interval.to_f
95
+ end
96
+
97
+ def recommended_threshold
98
+ heartbeat_interval * min_margin
99
+ end
100
+
101
+ def base_metadata
102
+ { heartbeat_interval: heartbeat_interval, alive_threshold: alive_threshold }
103
+ end
104
+
105
+ def humanize(seconds)
106
+ ActiveSupport::Duration.build(seconds).inspect
26
107
  end
27
108
  end
28
109
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SolidQueueGuard
4
- VERSION = '1.2.5'
4
+ VERSION = '1.3.0'
5
5
  end
metadata CHANGED
@@ -1,13 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: solid_queue_guard
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.5
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rafael Pissardo
8
+ autorequire:
8
9
  bindir: bin
9
10
  cert_chain: []
10
- date: 1980-01-02 00:00:00.000000000 Z
11
+ date: 2026-07-29 00:00:00.000000000 Z
11
12
  dependencies:
12
13
  - !ruby/object:Gem::Dependency
13
14
  name: actionpack
@@ -393,6 +394,7 @@ metadata:
393
394
  bug_tracker_uri: https://github.com/rafael-pissardo/solid_queue_guard/issues
394
395
  documentation_uri: https://github.com/rafael-pissardo/solid_queue_guard#readme
395
396
  rubygems_mfa_required: 'true'
397
+ post_install_message:
396
398
  rdoc_options: []
397
399
  require_paths:
398
400
  - lib
@@ -407,7 +409,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
407
409
  - !ruby/object:Gem::Version
408
410
  version: '0'
409
411
  requirements: []
410
- rubygems_version: 3.6.9
412
+ rubygems_version: 3.5.3
413
+ signing_key:
411
414
  specification_version: 4
412
415
  summary: Production readiness checks and runtime guards for Rails Solid Queue.
413
416
  test_files: []