solid_queue_guard 0.5.0 → 1.0.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.
Files changed (33) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +12 -0
  3. data/.rubocop.yml +44 -0
  4. data/.ruby-version +1 -0
  5. data/CHANGELOG.md +81 -0
  6. data/Gemfile +8 -0
  7. data/Gemfile.lock +308 -0
  8. data/README.md +66 -9
  9. data/app/controllers/solid_queue_guard/health_controller.rb +1 -4
  10. data/lib/generators/solid_queue_guard/install/USAGE.ci +9 -0
  11. data/lib/generators/solid_queue_guard/install/ci_generator.rb +19 -0
  12. data/lib/generators/solid_queue_guard/install/templates/solid_queue_guard.rb +6 -0
  13. data/lib/generators/solid_queue_guard/install/templates/solid_queue_guard.yml +25 -0
  14. data/lib/solid_queue_guard/checks/base.rb +16 -0
  15. data/lib/solid_queue_guard/checks/config/async_supervisor_config_check.rb +25 -0
  16. data/lib/solid_queue_guard/checks/config/puma_colocated_check.rb +5 -11
  17. data/lib/solid_queue_guard/checks/registry.rb +8 -2
  18. data/lib/solid_queue_guard/checks/runtime/database_support.rb +5 -2
  19. data/lib/solid_queue_guard/checks/runtime/dispatcher_check.rb +4 -2
  20. data/lib/solid_queue_guard/checks/runtime/failed_jobs_check.rb +1 -1
  21. data/lib/solid_queue_guard/checks/runtime/puma_plugin_runtime_check.rb +39 -0
  22. data/lib/solid_queue_guard/checks/runtime/recurring_stale_check.rb +1 -1
  23. data/lib/solid_queue_guard/checks/runtime/scheduled_backlog_check.rb +1 -1
  24. data/lib/solid_queue_guard/checks/runtime/stale_process_check.rb +1 -1
  25. data/lib/solid_queue_guard/configuration.rb +34 -1
  26. data/lib/solid_queue_guard/http_status_policy.rb +35 -0
  27. data/lib/solid_queue_guard/puma_plugin_support.rb +35 -0
  28. data/lib/solid_queue_guard/recommendations/topology.rb +13 -0
  29. data/lib/solid_queue_guard/runner.rb +10 -1
  30. data/lib/solid_queue_guard/version.rb +1 -1
  31. data/lib/solid_queue_guard.rb +1 -1
  32. data/solid_queue_guard.gemspec +54 -0
  33. metadata +15 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c3b3fded32011114a722d7207eb15c44dad0d1be1e0c5b3202bdaf32f84ea819
4
- data.tar.gz: 6ef2779a3372987138feb9a2dc9730ba7750c67a544a2c821029988877feb8de
3
+ metadata.gz: 690433fe81ac90880ec7fdaa046b7638330eb879776e19343066732fd1f0f3e7
4
+ data.tar.gz: 6028bf63b80b0919158a10fb5771b8cdec74518be47b0882cfd39f893bbf10f7
5
5
  SHA512:
6
- metadata.gz: 39c815be31c9ec06116840f813f57a6a9ebcb2dcad7c3747bf47d87cb59304fbdc6e629be2ffbb725eb649c913a75409c6b1e39bcb9c3e627ac00707af579e90
7
- data.tar.gz: c338648964e042b7d5fb485c8281bc1337ab54acfe693b886e9f8ed656135aa924fe8cbc89af3382003dafea8844ab01497e4205b92ae474b376b1419751d68d
6
+ metadata.gz: 2d9bf3c79fbe0871ed9456eec1cefb22baf52f4949b128cc2a1f8d30dde4bb468bbece87752a33ea06a0e53d12ec25db65e1c1295205ac140643d9cf5dbfc769
7
+ data.tar.gz: 0d40a0805708376a56e243977772274a61f6e4a799ca3dfc64dfb362a46217e30258ba1758e1dda7bc3956f63e13895cde6814f446551b4bf271a07b24477e57
data/.gitignore ADDED
@@ -0,0 +1,12 @@
1
+ /.bundle/
2
+ /Gemfile.lock.bak
3
+ /pkg/
4
+ /tmp/
5
+ /*.gem
6
+ /solid_queue_guard-*/
7
+
8
+ /test/dummy/db/*.sqlite3
9
+ /test/dummy/log/*
10
+ !/test/dummy/log/.keep
11
+ /test/dummy/tmp/*
12
+ !/test/dummy/tmp/.keep
data/.rubocop.yml ADDED
@@ -0,0 +1,44 @@
1
+ plugins:
2
+ - rubocop-rails
3
+
4
+ AllCops:
5
+ NewCops: enable
6
+ TargetRubyVersion: 3.1
7
+ SuggestExtensions: false
8
+ Exclude:
9
+ - "gemfiles/**/*"
10
+ - "test/dummy/**/*"
11
+ - "vendor/**/*"
12
+ - "tmp/**/*"
13
+
14
+ Style/Documentation:
15
+ Enabled: false
16
+
17
+ Metrics/BlockLength:
18
+ Exclude:
19
+ - "Rakefile"
20
+ - "*.gemspec"
21
+ - "lib/solid_queue_guard/tasks.rb"
22
+
23
+ Metrics/MethodLength:
24
+ Max: 25
25
+
26
+ Metrics/AbcSize:
27
+ Max: 25
28
+ Exclude:
29
+ - lib/solid_queue_guard/checks/runtime/**/*
30
+
31
+ Gemspec/DevelopmentDependencies:
32
+ Enabled: false
33
+
34
+ Rails/Exit:
35
+ Exclude:
36
+ - "lib/solid_queue_guard/cli.rb"
37
+
38
+ Naming/PredicateMethod:
39
+ Exclude:
40
+ - "lib/solid_queue_guard/tasks.rb"
41
+
42
+ Style/MultilineBlockChain:
43
+ Exclude:
44
+ - "lib/solid_queue_guard/checks/runtime/**/*"
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 3.4.9
data/CHANGELOG.md ADDED
@@ -0,0 +1,81 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [1.0.0] - 2026-07-09
9
+
10
+ ### Added
11
+
12
+ - Stable public API guarantee documented in README
13
+ - Gemspec packaging via `git ls-files` for reproducible releases
14
+
15
+ ### Changed
16
+
17
+ - Deprecations now target removal in `2.0` per semver policy
18
+
19
+ ## [0.8.0] - 2026-07-09
20
+
21
+ ### Added
22
+
23
+ - Configurable HTTP status policy via `degraded_http_status` and `unhealthy_http_status`
24
+ - `solid_queue_guard:install:ci` generator for GitHub Actions doctor workflow
25
+
26
+ ## [0.7.0] - 2026-07-09
27
+
28
+ ### Added
29
+
30
+ - `AsyncSupervisorConfigCheck` for async supervisor mode
31
+ - `PumaPluginRuntimeCheck` for co-located Puma plugin health
32
+ - Async-aware topology pool recommendations
33
+
34
+ ## [0.6.0] - 2026-07-09
35
+
36
+ ### Added
37
+
38
+ - Per-check configuration via `disabled_checks` and `config.checks`
39
+ - Per-check threshold overrides for queue lag, failed jobs, stale processes, and scheduled backlog
40
+
41
+ ## [0.5.0] - 2026-07-09
42
+
43
+ ### Added
44
+
45
+ - `TopologyRecommendationCheck` for automatic `queue.yml` and pool recommendations
46
+ - `SolidQueueGuard::Recommendations::Topology` analyzer
47
+
48
+ ## [0.4.0] - 2026-07-09
49
+
50
+ ### Added
51
+
52
+ - Metrics export via `config.metrics_backends` (`:statsd`, `:prometheus`, `:opentelemetry`)
53
+ - `SolidQueueGuard::Metrics::Exporter` and per-backend exporters
54
+
55
+ ## [0.3.0] - 2026-07-09
56
+
57
+ ### Added
58
+
59
+ - Notification adapters: `:rails_logger`, `:slack`, `:datadog`, `:webhook`
60
+ - Automatic notification delivery on degraded/unhealthy CLI reports via `config.notify_with`
61
+
62
+ ## [0.2.0] - 2026-07-09
63
+
64
+ ### Added
65
+
66
+ - Runtime checks: queue lag, stale processes, dispatcher health, scheduled backlog, blocked jobs, orphaned claims, failed jobs, recurring staleness, paused queue lag, pidfile, finished jobs growth
67
+ - HTTP `/solid_queue_guard/health` endpoint with optional token auth and response caching
68
+ - `health` rake task now runs full runtime scope
69
+ - Terminal report hides skipped runtime checks
70
+ - Optional Rails `/up` integration via `integrate_rails_health`
71
+
72
+ ## [0.1.0] - 2026-07-09
73
+
74
+ ### Added
75
+
76
+ - `solid_queue_guard:doctor` rake task for configuration readiness checks
77
+ - `solid_queue_guard:report` rake task for full diagnostic output
78
+ - `solid_queue_guard:install` generator for the initializer
79
+ - JSON output via `SOLID_QUEUE_GUARD_FORMAT=json` or `doctor[json]`
80
+ - Strict CI mode via `SOLID_QUEUE_GUARD_STRICT=1` or `--strict`
81
+ - Configuration checks: adapter, queue database, `connects_to`, queue schema, thread pool, worker coverage, scheduler, environment flags, process heartbeat thresholds, and Puma co-location
data/Gemfile ADDED
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ gemspec
6
+
7
+ # RuboCop 1.75+ can pull parallel 2.x, which requires Ruby >= 3.3.
8
+ gem 'parallel', '~> 1.26'
data/Gemfile.lock ADDED
@@ -0,0 +1,308 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ solid_queue_guard (1.0.0)
5
+ actionpack (>= 7.1, < 9.0)
6
+ activejob (>= 7.1, < 9.0)
7
+ activerecord (>= 7.1, < 9.0)
8
+ activesupport (>= 7.1, < 9.0)
9
+ railties (>= 7.1, < 9.0)
10
+ solid_queue (>= 1.0, < 2.0)
11
+
12
+ GEM
13
+ remote: https://rubygems.org/
14
+ specs:
15
+ action_text-trix (2.1.19)
16
+ railties
17
+ actioncable (8.1.3)
18
+ actionpack (= 8.1.3)
19
+ activesupport (= 8.1.3)
20
+ nio4r (~> 2.0)
21
+ websocket-driver (>= 0.6.1)
22
+ zeitwerk (~> 2.6)
23
+ actionmailbox (8.1.3)
24
+ actionpack (= 8.1.3)
25
+ activejob (= 8.1.3)
26
+ activerecord (= 8.1.3)
27
+ activestorage (= 8.1.3)
28
+ activesupport (= 8.1.3)
29
+ mail (>= 2.8.0)
30
+ actionmailer (8.1.3)
31
+ actionpack (= 8.1.3)
32
+ actionview (= 8.1.3)
33
+ activejob (= 8.1.3)
34
+ activesupport (= 8.1.3)
35
+ mail (>= 2.8.0)
36
+ rails-dom-testing (~> 2.2)
37
+ actionpack (8.1.3)
38
+ actionview (= 8.1.3)
39
+ activesupport (= 8.1.3)
40
+ nokogiri (>= 1.8.5)
41
+ rack (>= 2.2.4)
42
+ rack-session (>= 1.0.1)
43
+ rack-test (>= 0.6.3)
44
+ rails-dom-testing (~> 2.2)
45
+ rails-html-sanitizer (~> 1.6)
46
+ useragent (~> 0.16)
47
+ actiontext (8.1.3)
48
+ action_text-trix (~> 2.1.15)
49
+ actionpack (= 8.1.3)
50
+ activerecord (= 8.1.3)
51
+ activestorage (= 8.1.3)
52
+ activesupport (= 8.1.3)
53
+ globalid (>= 0.6.0)
54
+ nokogiri (>= 1.8.5)
55
+ actionview (8.1.3)
56
+ activesupport (= 8.1.3)
57
+ builder (~> 3.1)
58
+ erubi (~> 1.11)
59
+ rails-dom-testing (~> 2.2)
60
+ rails-html-sanitizer (~> 1.6)
61
+ activejob (8.1.3)
62
+ activesupport (= 8.1.3)
63
+ globalid (>= 0.3.6)
64
+ activemodel (8.1.3)
65
+ activesupport (= 8.1.3)
66
+ activerecord (8.1.3)
67
+ activemodel (= 8.1.3)
68
+ activesupport (= 8.1.3)
69
+ timeout (>= 0.4.0)
70
+ activestorage (8.1.3)
71
+ actionpack (= 8.1.3)
72
+ activejob (= 8.1.3)
73
+ activerecord (= 8.1.3)
74
+ activesupport (= 8.1.3)
75
+ marcel (~> 1.0)
76
+ activesupport (8.1.3)
77
+ base64
78
+ bigdecimal
79
+ concurrent-ruby (~> 1.0, >= 1.3.1)
80
+ connection_pool (>= 2.2.5)
81
+ drb
82
+ i18n (>= 1.6, < 2)
83
+ json
84
+ logger (>= 1.4.2)
85
+ minitest (>= 5.1)
86
+ securerandom (>= 0.3)
87
+ tzinfo (~> 2.0, >= 2.0.5)
88
+ uri (>= 0.13.1)
89
+ appraisal (2.5.0)
90
+ bundler
91
+ rake
92
+ thor (>= 0.14.0)
93
+ ast (2.4.3)
94
+ base64 (0.3.0)
95
+ bigdecimal (4.1.2)
96
+ builder (3.3.0)
97
+ concurrent-ruby (1.3.7)
98
+ connection_pool (3.0.2)
99
+ crass (1.0.7)
100
+ date (3.5.1)
101
+ debug (1.11.1)
102
+ irb (~> 1.10)
103
+ reline (>= 0.3.8)
104
+ drb (2.2.3)
105
+ erb (6.0.4)
106
+ erubi (1.13.1)
107
+ et-orbi (1.4.0)
108
+ tzinfo
109
+ fugit (1.12.3)
110
+ et-orbi (~> 1.4)
111
+ raabro (~> 1.4)
112
+ globalid (1.4.0)
113
+ activesupport (>= 6.1)
114
+ i18n (1.15.2)
115
+ concurrent-ruby (~> 1.0)
116
+ io-console (0.8.2)
117
+ irb (1.18.0)
118
+ pp (>= 0.6.0)
119
+ prism (>= 1.3.0)
120
+ rdoc (>= 4.0.0)
121
+ reline (>= 0.4.2)
122
+ json (2.20.0)
123
+ language_server-protocol (3.17.0.6)
124
+ lint_roller (1.1.0)
125
+ logger (1.7.0)
126
+ loofah (2.25.1)
127
+ crass (~> 1.0.2)
128
+ nokogiri (>= 1.12.0)
129
+ mail (2.9.1)
130
+ logger
131
+ mini_mime (>= 0.1.1)
132
+ net-imap
133
+ net-pop
134
+ net-smtp
135
+ marcel (1.2.1)
136
+ mini_mime (1.1.5)
137
+ minitest (5.27.0)
138
+ mocha (3.1.0)
139
+ ruby2_keywords (>= 0.0.5)
140
+ net-imap (0.6.4.1)
141
+ date
142
+ net-protocol
143
+ net-pop (0.1.2)
144
+ net-protocol
145
+ net-protocol (0.2.2)
146
+ timeout
147
+ net-smtp (0.5.1)
148
+ net-protocol
149
+ nio4r (2.7.5)
150
+ nokogiri (1.19.4-aarch64-linux-gnu)
151
+ racc (~> 1.4)
152
+ nokogiri (1.19.4-aarch64-linux-musl)
153
+ racc (~> 1.4)
154
+ nokogiri (1.19.4-arm-linux-gnu)
155
+ racc (~> 1.4)
156
+ nokogiri (1.19.4-arm-linux-musl)
157
+ racc (~> 1.4)
158
+ nokogiri (1.19.4-arm64-darwin)
159
+ racc (~> 1.4)
160
+ nokogiri (1.19.4-x86_64-darwin)
161
+ racc (~> 1.4)
162
+ nokogiri (1.19.4-x86_64-linux-gnu)
163
+ racc (~> 1.4)
164
+ nokogiri (1.19.4-x86_64-linux-musl)
165
+ racc (~> 1.4)
166
+ parallel (1.28.0)
167
+ parser (3.3.11.1)
168
+ ast (~> 2.4.1)
169
+ racc
170
+ pp (0.6.4)
171
+ prettyprint
172
+ prettyprint (0.2.0)
173
+ prism (1.9.0)
174
+ puma (8.0.2)
175
+ nio4r (~> 2.0)
176
+ raabro (1.4.0)
177
+ racc (1.8.1)
178
+ rack (3.2.6)
179
+ rack-session (2.1.2)
180
+ base64 (>= 0.1.0)
181
+ rack (>= 3.0.0)
182
+ rack-test (2.2.0)
183
+ rack (>= 1.3)
184
+ rackup (2.3.1)
185
+ rack (>= 3)
186
+ rails (8.1.3)
187
+ actioncable (= 8.1.3)
188
+ actionmailbox (= 8.1.3)
189
+ actionmailer (= 8.1.3)
190
+ actionpack (= 8.1.3)
191
+ actiontext (= 8.1.3)
192
+ actionview (= 8.1.3)
193
+ activejob (= 8.1.3)
194
+ activemodel (= 8.1.3)
195
+ activerecord (= 8.1.3)
196
+ activestorage (= 8.1.3)
197
+ activesupport (= 8.1.3)
198
+ bundler (>= 1.15.0)
199
+ railties (= 8.1.3)
200
+ rails-dom-testing (2.3.0)
201
+ activesupport (>= 5.0.0)
202
+ minitest
203
+ nokogiri (>= 1.6)
204
+ rails-html-sanitizer (1.7.0)
205
+ loofah (~> 2.25)
206
+ nokogiri (>= 1.15.7, != 1.16.7, != 1.16.6, != 1.16.5, != 1.16.4, != 1.16.3, != 1.16.2, != 1.16.1, != 1.16.0.rc1, != 1.16.0)
207
+ railties (8.1.3)
208
+ actionpack (= 8.1.3)
209
+ activesupport (= 8.1.3)
210
+ irb (~> 1.13)
211
+ rackup (>= 1.0.0)
212
+ rake (>= 12.2)
213
+ thor (~> 1.0, >= 1.2.2)
214
+ tsort (>= 0.2)
215
+ zeitwerk (~> 2.6)
216
+ rainbow (3.1.1)
217
+ rake (13.4.2)
218
+ rbs (4.0.3)
219
+ logger
220
+ prism (>= 1.6.0)
221
+ tsort
222
+ rdoc (8.0.0)
223
+ erb
224
+ prism (>= 1.6.0)
225
+ rbs (>= 4.0.0)
226
+ tsort
227
+ regexp_parser (2.12.0)
228
+ reline (0.6.3)
229
+ io-console (~> 0.5)
230
+ rubocop (1.88.2)
231
+ json (~> 2.3)
232
+ language_server-protocol (~> 3.17.0.2)
233
+ lint_roller (~> 1.1.0)
234
+ parallel (>= 1.10)
235
+ parser (>= 3.3.0.2)
236
+ rainbow (>= 2.2.2, < 4.0)
237
+ regexp_parser (>= 2.9.3, < 3.0)
238
+ rubocop-ast (>= 1.49.0, < 2.0)
239
+ ruby-progressbar (~> 1.7)
240
+ unicode-display_width (>= 2.4.0, < 4.0)
241
+ rubocop-ast (1.50.0)
242
+ parser (>= 3.3.7.2)
243
+ prism (~> 1.7)
244
+ rubocop-rails (2.35.5)
245
+ activesupport (>= 4.2.0)
246
+ lint_roller (~> 1.1)
247
+ rack (>= 1.1)
248
+ rubocop (>= 1.75.0, < 2.0)
249
+ rubocop-ast (>= 1.44.0, < 2.0)
250
+ ruby-progressbar (1.13.0)
251
+ ruby2_keywords (0.0.5)
252
+ securerandom (0.4.1)
253
+ solid_queue (1.4.0)
254
+ activejob (>= 7.1)
255
+ activerecord (>= 7.1)
256
+ concurrent-ruby (>= 1.3.1)
257
+ fugit (~> 1.11)
258
+ railties (>= 7.1)
259
+ thor (>= 1.3.1)
260
+ sqlite3 (2.9.5-aarch64-linux-gnu)
261
+ sqlite3 (2.9.5-aarch64-linux-musl)
262
+ sqlite3 (2.9.5-arm-linux-gnu)
263
+ sqlite3 (2.9.5-arm-linux-musl)
264
+ sqlite3 (2.9.5-arm64-darwin)
265
+ sqlite3 (2.9.5-x86_64-darwin)
266
+ sqlite3 (2.9.5-x86_64-linux-gnu)
267
+ sqlite3 (2.9.5-x86_64-linux-musl)
268
+ thor (1.5.0)
269
+ timeout (0.6.1)
270
+ tsort (0.2.0)
271
+ tzinfo (2.0.6)
272
+ concurrent-ruby (~> 1.0)
273
+ unicode-display_width (3.2.0)
274
+ unicode-emoji (~> 4.1)
275
+ unicode-emoji (4.2.0)
276
+ uri (1.1.1)
277
+ useragent (0.16.11)
278
+ websocket-driver (0.8.2)
279
+ base64
280
+ websocket-extensions (>= 0.1.0)
281
+ websocket-extensions (0.1.5)
282
+ zeitwerk (2.8.2)
283
+
284
+ PLATFORMS
285
+ aarch64-linux-gnu
286
+ aarch64-linux-musl
287
+ arm-linux-gnu
288
+ arm-linux-musl
289
+ arm64-darwin
290
+ x86_64-darwin
291
+ x86_64-linux-gnu
292
+ x86_64-linux-musl
293
+
294
+ DEPENDENCIES
295
+ appraisal (~> 2.5)
296
+ debug
297
+ minitest (~> 5.0)
298
+ mocha (>= 2.1)
299
+ parallel (~> 1.26)
300
+ puma (>= 6.0)
301
+ rails (>= 7.1, < 9.0)
302
+ rubocop (~> 1.75)
303
+ rubocop-rails (~> 2.30)
304
+ solid_queue_guard!
305
+ sqlite3 (~> 2.1)
306
+
307
+ BUNDLED WITH
308
+ 2.7.2
data/README.md CHANGED
@@ -67,7 +67,7 @@ One command. Actionable output. No Datadog required to get started.
67
67
 
68
68
  ## What it checks
69
69
 
70
- ### v0.1 — Configuration doctor (available now)
70
+ ### Configuration doctor
71
71
 
72
72
  Runs locally, in CI, or pre-deploy. **No extra infrastructure.**
73
73
 
@@ -83,8 +83,10 @@ Runs locally, in CI, or pre-deploy. **No extra infrastructure.**
83
83
  | **Env flags** | `SOLID_QUEUE_SKIP_RECURRING=true` in production |
84
84
  | **Heartbeats** | Default thresholds that may not fit your deploy |
85
85
  | **Puma plugin** | Solid Queue co-located with web in production |
86
+ | **Async supervisor** | `async` mode with thread/pool sizing risks |
87
+ | **Topology** | `queue.yml` worker and pool recommendations |
86
88
 
87
- ### v0.2+ — Runtime guards (roadmap)
89
+ ### Runtime guards
88
90
 
89
91
  | Check | Catches |
90
92
  | ----- | ------- |
@@ -93,6 +95,7 @@ Runs locally, in CI, or pre-deploy. **No extra infrastructure.**
93
95
  | **Dispatcher health** | Scheduled jobs never becoming ready |
94
96
  | **Blocked jobs** | Concurrency control silently holding jobs |
95
97
  | **Recurring staleness** | Cron tasks that stopped firing |
98
+ | **Puma plugin runtime** | Plugin enabled but no active Solid Queue processes |
96
99
  | **HTTP `/health`** | Kamal, ECS, K8s, UptimeRobot integration |
97
100
 
98
101
  ---
@@ -104,6 +107,7 @@ Runs locally, in CI, or pre-deploy. **No extra infrastructure.**
104
107
  ```bash
105
108
  bundle add solid_queue_guard
106
109
  bin/rails solid_queue_guard:install
110
+ bin/rails generate solid_queue_guard:install:ci # optional GitHub Actions workflow
107
111
  ```
108
112
 
109
113
  ### Run the doctor
@@ -138,6 +142,12 @@ Perfect for deploy pipelines:
138
142
  run: SOLID_QUEUE_GUARD_STRICT=1 bin/rails solid_queue_guard:doctor
139
143
  ```
140
144
 
145
+ Or generate a workflow:
146
+
147
+ ```bash
148
+ bin/rails generate solid_queue_guard:install:ci
149
+ ```
150
+
141
151
  ### HTTP health
142
152
 
143
153
  ```ruby
@@ -157,6 +167,13 @@ config.health_token = ENV["SOLID_QUEUE_GUARD_TOKEN"]
157
167
  # curl -H "X-Solid-Queue-Guard-Token: $TOKEN" ...
158
168
  ```
159
169
 
170
+ HTTP status policy (for Kamal, ECS, load balancers):
171
+
172
+ ```ruby
173
+ config.degraded_http_status = 207 # or :ok (200), 503, etc.
174
+ config.unhealthy_http_status = 503 # default
175
+ ```
176
+
160
177
  Works with **Kamal**, **Heroku**, **Fly.io**, **ECS/Fargate**, **Kubernetes**, **Better Stack**, **UptimeRobot**.
161
178
 
162
179
  ---
@@ -177,13 +194,46 @@ SolidQueueGuard.configure do |config|
177
194
  config.failed_jobs_threshold = 20
178
195
  config.stale_process_threshold = 5.minutes
179
196
 
180
- # config.health_token = ENV["SOLID_QUEUE_GUARD_TOKEN"] # v0.2
181
- # config.notify_with = [:rails_logger, :slack] # v0.3
197
+ # Per-check overrides (v0.6+)
198
+ config.disabled_checks = [:pidfile]
199
+ config.checks.queue_lag = { threshold: 10.minutes }
200
+ config.checks.failed_jobs = { threshold: 5, enabled: true }
201
+
202
+ # HTTP status policy (v0.8+)
203
+ # config.degraded_http_status = 207
204
+ # config.unhealthy_http_status = 503
205
+
206
+ # config.health_token = ENV["SOLID_QUEUE_GUARD_TOKEN"]
207
+ # config.integrate_rails_health = true
208
+ # config.notify_with = [:rails_logger, :slack, :datadog, :webhook]
209
+ # config.metrics_backends = [:statsd, :prometheus, :opentelemetry]
182
210
  end
183
211
  ```
184
212
 
185
213
  ---
186
214
 
215
+ ## Public API (v1.0+)
216
+
217
+ The following surface is **stable** until `2.0` and follows [semantic versioning](https://semver.org/):
218
+
219
+ | API | Description |
220
+ | --- | ----------- |
221
+ | `SolidQueueGuard.configure` | Block-style configuration |
222
+ | `SolidQueueGuard.config` | Current configuration object |
223
+ | `SolidQueueGuard.enabled?` | Whether checks run |
224
+ | `solid_queue_guard:doctor` | Config readiness report |
225
+ | `solid_queue_guard:health` | Runtime health report |
226
+ | `solid_queue_guard:report` | Full diagnostic report |
227
+ | `solid_queue_guard:install` | Initializer generator |
228
+ | `solid_queue_guard:install:ci` | GitHub Actions workflow generator |
229
+ | `mount SolidQueueGuard::Engine` | HTTP health endpoint |
230
+
231
+ Configuration attributes, rake tasks, and health JSON shape are public. Internal check classes and registry are `@api private`.
232
+
233
+ Breaking changes ship only in major versions (`2.0+`). Deprecations warn one minor version ahead.
234
+
235
+ ---
236
+
187
237
  ## solid_queue_guard vs Mission Control
188
238
 
189
239
  | | [Mission Control — Jobs](https://github.com/rails/mission_control-jobs) | solid_queue_guard |
@@ -192,9 +242,9 @@ end
192
242
  | **UI** | Dashboard | CLI + JSON + health endpoint |
193
243
  | **Retry / discard** | Yes | No (use Mission Control) |
194
244
  | **Config doctor** | No | Yes |
195
- | **Queue lag alerts** | No | Yes (v0.2) |
245
+ | **Queue lag alerts** | No | Yes |
196
246
  | **Pre-deploy checks** | No | Yes |
197
- | **Recurring job guard** | Manual inspection | Automatic (v0.2) |
247
+ | **Recurring job guard** | Manual inspection | Automatic |
198
248
 
199
249
  **Use both.** They solve different problems.
200
250
 
@@ -202,13 +252,17 @@ end
202
252
 
203
253
  ## Roadmap
204
254
 
205
- | Version | Ships |
206
- | ------- | ----- |
255
+ | Version | Ships | Status |
256
+ | ------- | ----- | ------ |
207
257
  | **v0.1** | `doctor` — config checks, CI integration, install generator | ✅ Released |
208
258
  | **v0.2** | Runtime health, queue lag, dispatcher/blocked jobs, HTTP endpoint | ✅ Released |
209
259
  | **v0.3** | Slack, Datadog, webhook notifications | ✅ Released |
210
260
  | **v0.4** | StatsD, Prometheus, OpenTelemetry metrics | ✅ Released |
211
261
  | **v0.5** | Auto-recommendations for `queue.yml` topology | ✅ Released |
262
+ | **v0.6** | Per-check configuration (`disabled_checks`, `config.checks`) | ✅ Released |
263
+ | **v0.7** | Puma plugin runtime check, async supervisor awareness | ✅ Released |
264
+ | **v0.8** | HTTP status policy, `install:ci` generator | ✅ Released |
265
+ | **v1.0** | Stable public API, strict semver | ✅ Released |
212
266
 
213
267
  ---
214
268
 
@@ -216,8 +270,9 @@ end
216
270
 
217
271
  | Gem version | Ruby | Rails |
218
272
  | ----------- | ---- | ----- |
219
- | 0.1.x | 3.1+ | 7.1, 7.2, 8.0 |
273
+ | 1.0.x | 3.1+ | 7.1, 7.2, 8.0 |
220
274
  | 0.5.x | 3.1+ | 7.1, 7.2, 8.0 |
275
+ | 0.1.x | 3.1+ | 7.1, 7.2, 8.0 |
221
276
 
222
277
  ## Requirements
223
278
 
@@ -240,6 +295,8 @@ bundle exec appraisal install
240
295
  bundle exec appraisal rake test
241
296
  ```
242
297
 
298
+ Release a new version by pushing a `v*` tag after CI passes (Trusted Publishing on RubyGems).
299
+
243
300
  ---
244
301
 
245
302
  ## Contributing
@@ -24,10 +24,7 @@ module SolidQueueGuard
24
24
  end
25
25
 
26
26
  def http_status_for(status)
27
- case status.to_s
28
- when 'unhealthy' then :service_unavailable
29
- else :ok
30
- end
27
+ HttpStatusPolicy.for_report_status(status)
31
28
  end
32
29
  end
33
30
  end
@@ -0,0 +1,9 @@
1
+ Description:
2
+ Adds a GitHub Actions workflow that runs `solid_queue_guard:doctor` with strict mode.
3
+
4
+ Example:
5
+ bin/rails generate solid_queue_guard:install:ci
6
+
7
+ This will create:
8
+
9
+ .github/workflows/solid_queue_guard.yml
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails/generators/base'
4
+
5
+ module SolidQueueGuard
6
+ module Generators
7
+ module Install
8
+ class CiGenerator < Rails::Generators::Base
9
+ source_root File.expand_path('templates', __dir__)
10
+
11
+ desc 'Adds a GitHub Actions workflow that runs solid_queue_guard:doctor in CI'
12
+
13
+ def copy_workflow
14
+ template 'solid_queue_guard.yml', '.github/workflows/solid_queue_guard.yml'
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -14,6 +14,12 @@ SolidQueueGuard.configure do |config|
14
14
  config.health_cache_ttl = 15.seconds
15
15
  config.scheduled_backlog_threshold = 100
16
16
 
17
+ # config.disabled_checks = [:pidfile]
18
+ # config.checks.queue_lag = { threshold: 10.minutes }
19
+ # config.checks.failed_jobs = { threshold: 5, enabled: true }
20
+ # config.degraded_http_status = 207
21
+ # config.unhealthy_http_status = 503
22
+
17
23
  # config.health_token = ENV["SOLID_QUEUE_GUARD_TOKEN"]
18
24
  # config.integrate_rails_health = true
19
25
  # config.notify_with = [:rails_logger, :slack, :datadog, :webhook]
@@ -0,0 +1,25 @@
1
+ name: Solid Queue Guard
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+
8
+ jobs:
9
+ doctor:
10
+ name: Solid Queue production readiness
11
+ runs-on: ubuntu-latest
12
+
13
+ steps:
14
+ - uses: actions/checkout@v4
15
+
16
+ - uses: ruby/setup-ruby@v1
17
+ with:
18
+ ruby-version: .ruby-version
19
+ bundler-cache: true
20
+
21
+ - name: Prepare test database
22
+ run: bin/rails db:test:prepare
23
+
24
+ - name: Run Solid Queue Guard doctor
25
+ run: SOLID_QUEUE_GUARD_STRICT=1 bin/rails solid_queue_guard:doctor
@@ -8,6 +8,10 @@ module SolidQueueGuard
8
8
  new(**options).call
9
9
  end
10
10
 
11
+ def self.check_id
12
+ name.demodulize.underscore.delete_suffix('_check')
13
+ end
14
+
11
15
  def initialize(**options)
12
16
  @options = options
13
17
  end
@@ -47,6 +51,18 @@ module SolidQueueGuard
47
51
  def solid_queue_configuration
48
52
  @solid_queue_configuration ||= SolidQueue::Configuration.new
49
53
  end
54
+
55
+ def check_id
56
+ self.class.check_id
57
+ end
58
+
59
+ def guard_config
60
+ SolidQueueGuard.config
61
+ end
62
+
63
+ def check_setting(key, default = nil)
64
+ guard_config.check_setting(check_id, key, default)
65
+ end
50
66
  end
51
67
  end
52
68
  end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SolidQueueGuard
4
+ module Checks
5
+ module Config
6
+ class AsyncSupervisorConfigCheck < Base
7
+ def call
8
+ if PumaPluginSupport.async_supervisor_mode?
9
+ warn(
10
+ check_id,
11
+ 'Solid Queue supervisor is running in async mode',
12
+ suggestion: [
13
+ 'Review thread and database pool sizing;',
14
+ 'the processes option in queue.yml is ignored in async mode'
15
+ ].join(' '),
16
+ metadata: { supervisor_mode: 'async' }
17
+ )
18
+ else
19
+ pass(check_id, 'Solid Queue supervisor is running in fork mode')
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -4,27 +4,21 @@ module SolidQueueGuard
4
4
  module Checks
5
5
  module Config
6
6
  class PumaColocatedCheck < Base
7
- PUMA_PLUGIN_PATTERN = /plugin\s+:?solid_queue/
8
-
9
7
  def call
10
- puma_config = rails_root.join('config/puma.rb')
11
-
12
- return pass('puma_colocated', 'No config/puma.rb found') unless puma_config.exist?
13
-
14
- content = puma_config.read
8
+ return pass(check_id, 'No config/puma.rb found') unless PumaPluginSupport.puma_config_path.exist?
15
9
 
16
- if content.match?(PUMA_PLUGIN_PATTERN)
10
+ if PumaPluginSupport.puma_plugin_enabled?
17
11
  if Rails.env.production?
18
12
  warn(
19
- 'puma_colocated',
13
+ check_id,
20
14
  'Solid Queue Puma plugin is enabled in production',
21
15
  suggestion: 'Run Solid Queue in a dedicated job process for better isolation and memory management'
22
16
  )
23
17
  else
24
- pass('puma_colocated', 'Solid Queue Puma plugin detected (non-production environment)')
18
+ pass(check_id, 'Solid Queue Puma plugin detected (non-production environment)')
25
19
  end
26
20
  else
27
- pass('puma_colocated', 'Solid Queue is not co-located with Puma')
21
+ pass(check_id, 'Solid Queue is not co-located with Puma')
28
22
  end
29
23
  end
30
24
  end
@@ -15,7 +15,8 @@ module SolidQueueGuard
15
15
  Config::EnvFlagsCheck,
16
16
  Config::ProcessHeartbeatConfigCheck,
17
17
  Config::PumaColocatedCheck,
18
- Config::TopologyRecommendationCheck
18
+ Config::TopologyRecommendationCheck,
19
+ Config::AsyncSupervisorConfigCheck
19
20
  ].freeze
20
21
 
21
22
  RUNTIME_CHECKS = [
@@ -30,10 +31,15 @@ module SolidQueueGuard
30
31
  Runtime::RecurringStaleCheck,
31
32
  Runtime::PausedQueueLagCheck,
32
33
  Runtime::PidfileCheck,
33
- Runtime::FinishedJobsGrowthCheck
34
+ Runtime::FinishedJobsGrowthCheck,
35
+ Runtime::PumaPluginRuntimeCheck
34
36
  ].freeze
35
37
 
36
38
  class << self
39
+ def check_id_for(check_class)
40
+ check_class.check_id
41
+ end
42
+
37
43
  def for(scope)
38
44
  case scope.to_sym
39
45
  when :config then CONFIG_CHECKS
@@ -28,8 +28,11 @@ module SolidQueueGuard
28
28
  end
29
29
 
30
30
  def lag_threshold_for(queue_name)
31
- thresholds = config.queue_lag_thresholds
32
- thresholds[queue_name.to_sym] || thresholds[queue_name] || thresholds[:default]
31
+ thresholds = config.check_setting(:queue_lag, :thresholds, config.queue_lag_thresholds)
32
+ per_queue = thresholds[queue_name.to_sym] || thresholds[queue_name]
33
+ return per_queue if per_queue
34
+
35
+ config.check_setting(:queue_lag, :threshold, thresholds[:default])
33
36
  end
34
37
  end
35
38
  end
@@ -9,16 +9,18 @@ module SolidQueueGuard
9
9
  dispatchers = SolidQueue::Process.where(kind: 'Dispatcher')
10
10
  due_count = SolidQueue::ScheduledExecution.due.count
11
11
 
12
+ threshold = config.check_setting(:scheduled_backlog, :threshold, config.scheduled_backlog_threshold)
13
+
12
14
  if dispatchers.none? && due_count.positive?
13
15
  failure(
14
16
  check_id,
15
17
  "#{due_count} scheduled job(s) are due but no dispatcher is running",
16
18
  suggestion: 'Start a dispatcher process or verify bin/jobs is running'
17
19
  )
18
- elsif due_count > config.scheduled_backlog_threshold
20
+ elsif due_count > threshold
19
21
  warn(
20
22
  check_id,
21
- "#{due_count} scheduled executions are due (threshold: #{config.scheduled_backlog_threshold})",
23
+ "#{due_count} scheduled executions are due (threshold: #{threshold})",
22
24
  suggestion: 'Verify the dispatcher is keeping up with scheduled work'
23
25
  )
24
26
  else
@@ -9,7 +9,7 @@ module SolidQueueGuard
9
9
  def call
10
10
  with_queue_database do
11
11
  count = SolidQueue::FailedExecution.where(created_at: WINDOW.ago..).count
12
- threshold = config.failed_jobs_threshold
12
+ threshold = config.check_setting(:failed_jobs, :threshold, config.failed_jobs_threshold)
13
13
 
14
14
  if count > threshold
15
15
  warn(
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SolidQueueGuard
4
+ module Checks
5
+ module Runtime
6
+ class PumaPluginRuntimeCheck < Base
7
+ def call
8
+ return skip(check_id, 'Solid Queue Puma plugin is not enabled') unless PumaPluginSupport.puma_plugin_enabled?
9
+
10
+ with_queue_database do
11
+ threshold = config.check_setting(:puma_plugin_runtime, :threshold, config.stale_process_threshold)
12
+ active = SolidQueue::Process.where(last_heartbeat_at: threshold.ago..)
13
+
14
+ if active.any?
15
+ pass(
16
+ check_id,
17
+ "Solid Queue processes are active via Puma plugin (#{active.count} process(es))",
18
+ metadata: { active_processes: active.count, supervisor_mode: supervisor_mode_label }
19
+ )
20
+ else
21
+ failure(
22
+ check_id,
23
+ 'Solid Queue Puma plugin is enabled but no active processes were found',
24
+ suggestion: 'Verify the Puma plugin booted Solid Queue and workers are processing jobs',
25
+ metadata: { supervisor_mode: supervisor_mode_label }
26
+ )
27
+ end
28
+ end
29
+ end
30
+
31
+ private
32
+
33
+ def supervisor_mode_label
34
+ PumaPluginSupport.async_supervisor_mode? ? 'async' : 'fork'
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -29,7 +29,7 @@ module SolidQueueGuard
29
29
  private
30
30
 
31
31
  def expected_staleness
32
- config.stale_process_threshold * 2
32
+ config.check_setting(:recurring_stale, :threshold, config.stale_process_threshold * 2)
33
33
  end
34
34
  end
35
35
  end
@@ -7,7 +7,7 @@ module SolidQueueGuard
7
7
  def call
8
8
  with_queue_database do
9
9
  due_count = SolidQueue::ScheduledExecution.due.count
10
- threshold = config.scheduled_backlog_threshold
10
+ threshold = config.check_setting(:scheduled_backlog, :threshold, config.scheduled_backlog_threshold)
11
11
 
12
12
  if due_count > threshold
13
13
  warn(
@@ -6,7 +6,7 @@ module SolidQueueGuard
6
6
  class StaleProcessCheck < Base
7
7
  def call
8
8
  with_queue_database do
9
- threshold = config.stale_process_threshold
9
+ threshold = config.check_setting(:stale_process, :threshold, config.stale_process_threshold)
10
10
  stale = SolidQueue::Process.where(last_heartbeat_at: ...threshold.ago)
11
11
 
12
12
  if stale.none?
@@ -12,7 +12,11 @@ module SolidQueueGuard
12
12
  :scheduled_backlog_threshold,
13
13
  :integrate_rails_health,
14
14
  :notify_with,
15
- :metrics_backends
15
+ :metrics_backends,
16
+ :disabled_checks,
17
+ :checks,
18
+ :degraded_http_status,
19
+ :unhealthy_http_status
16
20
 
17
21
  def initialize
18
22
  @enabled = true
@@ -26,10 +30,39 @@ module SolidQueueGuard
26
30
  @integrate_rails_health = false
27
31
  @notify_with = [:rails_logger]
28
32
  @metrics_backends = []
33
+ @disabled_checks = []
34
+ @checks = ActiveSupport::OrderedOptions.new
35
+ @degraded_http_status = :ok
36
+ @unhealthy_http_status = :service_unavailable
29
37
  end
30
38
 
31
39
  def strict?
32
40
  strict_mode || ActiveModel::Type::Boolean.new.cast(ENV.fetch('SOLID_QUEUE_GUARD_STRICT', nil))
33
41
  end
42
+
43
+ def check_enabled?(check_id)
44
+ id = check_id.to_sym
45
+ return false if disabled_checks.map(&:to_sym).include?(id)
46
+
47
+ settings = check_settings_for(id)
48
+ return true if settings.nil?
49
+
50
+ enabled_value = settings[:enabled]
51
+ enabled_value = settings['enabled'] if enabled_value.nil?
52
+ enabled_value != false
53
+ end
54
+
55
+ def check_settings_for(check_id)
56
+ checks[check_id.to_sym] || checks[check_id.to_s]
57
+ end
58
+
59
+ def check_setting(check_id, key, default = nil)
60
+ settings = check_settings_for(check_id)
61
+ return default unless settings
62
+
63
+ value = settings[key]
64
+ value = settings[key.to_sym] if value.nil?
65
+ value.nil? ? default : value
66
+ end
34
67
  end
35
68
  end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SolidQueueGuard
4
+ # @api private
5
+ module HttpStatusPolicy
6
+ module_function
7
+
8
+ STATUS_MAP = {
9
+ ok: :ok,
10
+ success: :ok,
11
+ 200 => :ok,
12
+ multi_status: :multi_status,
13
+ 207 => :multi_status,
14
+ service_unavailable: :service_unavailable,
15
+ unavailable: :service_unavailable,
16
+ 503 => :service_unavailable
17
+ }.freeze
18
+
19
+ def resolve(status)
20
+ key = status.is_a?(Integer) ? status : status.to_sym
21
+ STATUS_MAP.fetch(key, :ok)
22
+ end
23
+
24
+ def for_report_status(report_status, config: SolidQueueGuard.config)
25
+ case report_status.to_s
26
+ when 'unhealthy'
27
+ resolve(config.unhealthy_http_status)
28
+ when 'degraded'
29
+ resolve(config.degraded_http_status)
30
+ else
31
+ :ok
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SolidQueueGuard
4
+ # @api private
5
+ module PumaPluginSupport
6
+ module_function
7
+
8
+ PUMA_PLUGIN_PATTERN = /plugin\s+:?solid_queue/
9
+ ASYNC_MODE_PATTERN = /solid_queue_mode\s+:?async/
10
+
11
+ def puma_config_path
12
+ Rails.root.join('config/puma.rb')
13
+ end
14
+
15
+ def puma_config_content
16
+ return unless puma_config_path.exist?
17
+
18
+ puma_config_path.read
19
+ end
20
+
21
+ def puma_plugin_enabled?
22
+ content = puma_config_content
23
+ content.present? && content.match?(PUMA_PLUGIN_PATTERN)
24
+ end
25
+
26
+ def puma_async_mode?
27
+ content = puma_config_content
28
+ content.present? && content.match?(ASYNC_MODE_PATTERN)
29
+ end
30
+
31
+ def async_supervisor_mode?
32
+ ENV.fetch('SOLID_QUEUE_SUPERVISOR_MODE', 'fork').casecmp('async').zero? || puma_async_mode?
33
+ end
34
+ end
35
+ end
@@ -31,6 +31,8 @@ module SolidQueueGuard
31
31
  end
32
32
 
33
33
  def pool_recommendations
34
+ return async_pool_recommendation if PumaPluginSupport.async_supervisor_mode?
35
+
34
36
  required_threads = configuration.estimated_number_of_threads
35
37
  pool_size = SolidQueue::Record.connection_pool&.size
36
38
  return [] if pool_size.nil? || required_threads <= pool_size
@@ -58,6 +60,17 @@ module SolidQueueGuard
58
60
  rescue StandardError
59
61
  false
60
62
  end
63
+
64
+ def async_pool_recommendation
65
+ required_threads = configuration.estimated_number_of_threads
66
+ pool_size = SolidQueue::Record.connection_pool&.size
67
+ return [] if pool_size.nil? || required_threads <= pool_size
68
+
69
+ ["Increase queue DB pool to at least #{required_threads + 2} " \
70
+ "for async supervisor mode (currently #{pool_size})"]
71
+ rescue StandardError
72
+ []
73
+ end
61
74
  end
62
75
  end
63
76
  end
@@ -27,10 +27,19 @@ module SolidQueueGuard
27
27
  end
28
28
 
29
29
  def run_check(check_class)
30
+ check_id = Checks::Registry.check_id_for(check_class)
31
+ unless SolidQueueGuard.config.check_enabled?(check_id)
32
+ return Check::Result.new(
33
+ id: check_id,
34
+ status: :skip,
35
+ message: 'Check disabled via configuration'
36
+ )
37
+ end
38
+
30
39
  check_class.call
31
40
  rescue StandardError => e
32
41
  Check::Result.new(
33
- id: check_class.name.demodulize.underscore,
42
+ id: check_id,
34
43
  status: :fail,
35
44
  message: "Check raised an error: #{e.class}: #{e.message}"
36
45
  )
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SolidQueueGuard
4
- VERSION = '0.5.0'
4
+ VERSION = '1.0.0'
5
5
  end
@@ -18,7 +18,7 @@ module SolidQueueGuard
18
18
  attr_accessor :configuration
19
19
 
20
20
  def deprecator
21
- @deprecator ||= ActiveSupport::Deprecation.new('0.2', 'SolidQueueGuard')
21
+ @deprecator ||= ActiveSupport::Deprecation.new('2.0', 'SolidQueueGuard')
22
22
  end
23
23
 
24
24
  def configure
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'lib/solid_queue_guard/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = 'solid_queue_guard'
7
+ spec.version = SolidQueueGuard::VERSION
8
+ spec.authors = ['Rafael Pissardo']
9
+ spec.email = ['rpissardo@users.noreply.github.com']
10
+ spec.homepage = 'https://github.com/rafael-pissardo/solid_queue_guard'
11
+ spec.summary = 'Production readiness checks and runtime guards for Rails Solid Queue.'
12
+ spec.description = [
13
+ 'Detect queue lag, dead workers, unsafe thread/pool configuration,',
14
+ 'and broken recurring jobs before they become incidents.'
15
+ ].join(' ')
16
+ spec.license = 'MIT'
17
+
18
+ spec.metadata = {
19
+ 'homepage_uri' => spec.homepage,
20
+ 'source_code_uri' => 'https://github.com/rafael-pissardo/solid_queue_guard',
21
+ 'changelog_uri' => 'https://github.com/rafael-pissardo/solid_queue_guard/blob/main/CHANGELOG.md',
22
+ 'bug_tracker_uri' => 'https://github.com/rafael-pissardo/solid_queue_guard/issues',
23
+ 'documentation_uri' => 'https://github.com/rafael-pissardo/solid_queue_guard#readme',
24
+ 'rubygems_mfa_required' => 'true'
25
+ }
26
+
27
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
28
+ `git ls-files -z`.split("\x0").reject do |file|
29
+ file.start_with?('test/', '.github/', 'docs/', 'script/', 'gemfiles/', 'Appraisals')
30
+ end
31
+ end
32
+
33
+ spec.require_paths = ['lib']
34
+ spec.required_ruby_version = '>= 3.1'
35
+
36
+ rails_version = '>= 7.1', '< 9.0'
37
+
38
+ spec.add_dependency 'actionpack', rails_version
39
+ spec.add_dependency 'activejob', rails_version
40
+ spec.add_dependency 'activerecord', rails_version
41
+ spec.add_dependency 'activesupport', rails_version
42
+ spec.add_dependency 'railties', rails_version
43
+ spec.add_dependency 'solid_queue', '>= 1.0', '< 2.0'
44
+
45
+ spec.add_development_dependency 'appraisal', '~> 2.5'
46
+ spec.add_development_dependency 'debug'
47
+ spec.add_development_dependency 'minitest', '~> 5.0'
48
+ spec.add_development_dependency 'mocha', '>= 2.1'
49
+ spec.add_development_dependency 'puma', '>= 6.0'
50
+ spec.add_development_dependency 'rails', rails_version
51
+ spec.add_development_dependency 'rubocop', '~> 1.75'
52
+ spec.add_development_dependency 'rubocop-rails', '~> 2.30'
53
+ spec.add_development_dependency 'sqlite3', '~> 2.1'
54
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: solid_queue_guard
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rafael Pissardo
@@ -269,6 +269,12 @@ executables: []
269
269
  extensions: []
270
270
  extra_rdoc_files: []
271
271
  files:
272
+ - ".gitignore"
273
+ - ".rubocop.yml"
274
+ - ".ruby-version"
275
+ - CHANGELOG.md
276
+ - Gemfile
277
+ - Gemfile.lock
272
278
  - MIT-LICENSE
273
279
  - README.md
274
280
  - Rakefile
@@ -276,12 +282,16 @@ files:
276
282
  - app/controllers/solid_queue_guard/health_controller.rb
277
283
  - config/routes.rb
278
284
  - lib/generators/solid_queue_guard/install/USAGE
285
+ - lib/generators/solid_queue_guard/install/USAGE.ci
286
+ - lib/generators/solid_queue_guard/install/ci_generator.rb
279
287
  - lib/generators/solid_queue_guard/install/install_generator.rb
280
288
  - lib/generators/solid_queue_guard/install/templates/solid_queue_guard.rb
289
+ - lib/generators/solid_queue_guard/install/templates/solid_queue_guard.yml
281
290
  - lib/solid_queue_guard.rb
282
291
  - lib/solid_queue_guard/check/result.rb
283
292
  - lib/solid_queue_guard/checks/base.rb
284
293
  - lib/solid_queue_guard/checks/config/adapter_check.rb
294
+ - lib/solid_queue_guard/checks/config/async_supervisor_config_check.rb
285
295
  - lib/solid_queue_guard/checks/config/connects_to_check.rb
286
296
  - lib/solid_queue_guard/checks/config/env_flags_check.rb
287
297
  - lib/solid_queue_guard/checks/config/process_heartbeat_config_check.rb
@@ -303,6 +313,7 @@ files:
303
313
  - lib/solid_queue_guard/checks/runtime/paused_queue_lag_check.rb
304
314
  - lib/solid_queue_guard/checks/runtime/pidfile_check.rb
305
315
  - lib/solid_queue_guard/checks/runtime/process_topology_check.rb
316
+ - lib/solid_queue_guard/checks/runtime/puma_plugin_runtime_check.rb
306
317
  - lib/solid_queue_guard/checks/runtime/queue_lag_check.rb
307
318
  - lib/solid_queue_guard/checks/runtime/recurring_stale_check.rb
308
319
  - lib/solid_queue_guard/checks/runtime/scheduled_backlog_check.rb
@@ -314,18 +325,21 @@ files:
314
325
  - lib/solid_queue_guard/formatters/terminal.rb
315
326
  - lib/solid_queue_guard/health/cache.rb
316
327
  - lib/solid_queue_guard/health/payload.rb
328
+ - lib/solid_queue_guard/http_status_policy.rb
317
329
  - lib/solid_queue_guard/metrics/exporter.rb
318
330
  - lib/solid_queue_guard/metrics/open_telemetry.rb
319
331
  - lib/solid_queue_guard/metrics/prometheus.rb
320
332
  - lib/solid_queue_guard/metrics/statsd.rb
321
333
  - lib/solid_queue_guard/notifier.rb
322
334
  - lib/solid_queue_guard/notifiers/base.rb
335
+ - lib/solid_queue_guard/puma_plugin_support.rb
323
336
  - lib/solid_queue_guard/queue_coverage.rb
324
337
  - lib/solid_queue_guard/recommendations/topology.rb
325
338
  - lib/solid_queue_guard/report.rb
326
339
  - lib/solid_queue_guard/runner.rb
327
340
  - lib/solid_queue_guard/tasks.rb
328
341
  - lib/solid_queue_guard/version.rb
342
+ - solid_queue_guard.gemspec
329
343
  homepage: https://github.com/rafael-pissardo/solid_queue_guard
330
344
  licenses:
331
345
  - MIT