good_job 2.6.2 → 2.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +13 -0
- data/README.md +57 -0
- data/engine/app/controllers/good_job/base_controller.rb +19 -0
- data/lib/good_job/cli.rb +8 -0
- data/lib/good_job/configuration.rb +7 -0
- data/lib/good_job/probe_server.rb +51 -0
- data/lib/good_job/version.rb +1 -1
- metadata +17 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f44a377e368104479ccd928977d0c99c673e468fdcce61530cdfef1ee045c61d
|
4
|
+
data.tar.gz: 3a5b29ba222be53ee571036ed27275517cb810a03bbd9b6fa5733b215742ef50
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 833b35f3faa5660d45e14adbb15d2b6f65c7a7cbc127ae0d6d9085844e55fe33c6c1b02cbb6196f5f753bdf7ec76cff18a1976cef3ca26288960f6028c6d3fac
|
7
|
+
data.tar.gz: def64d311e93139e7232fddd9aec1f0c0e0ff49696680dede67f87705d3a0dbc9338d083f1f2a22fdfff572465032c6ec75c97dee1ece7ffac20ca46c76fdc6c
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,18 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## [v2.7.0](https://github.com/bensheldon/good_job/tree/v2.7.0) (2021-11-10)
|
4
|
+
|
5
|
+
[Full Changelog](https://github.com/bensheldon/good_job/compare/v2.6.2...v2.7.0)
|
6
|
+
|
7
|
+
**Implemented enhancements:**
|
8
|
+
|
9
|
+
- Add http probe for CLI healthcheck/readiness/liveliness [\#452](https://github.com/bensheldon/good_job/pull/452) ([bensheldon](https://github.com/bensheldon))
|
10
|
+
- Add explicit Content Security Policy \(CSP\) for Dashboard [\#449](https://github.com/bensheldon/good_job/pull/449) ([bensheldon](https://github.com/bensheldon))
|
11
|
+
|
12
|
+
**Closed issues:**
|
13
|
+
|
14
|
+
- Add a default Content-Security-Policy for the Dashboard [\#420](https://github.com/bensheldon/good_job/issues/420)
|
15
|
+
|
3
16
|
## [v2.6.2](https://github.com/bensheldon/good_job/tree/v2.6.2) (2021-11-05)
|
4
17
|
|
5
18
|
[Full Changelog](https://github.com/bensheldon/good_job/compare/v2.6.1...v2.6.2)
|
data/README.md
CHANGED
@@ -55,6 +55,7 @@ For more of the story of GoodJob, read the [introductory blog post](https://isla
|
|
55
55
|
- [Migrate to GoodJob from a different ActiveJob backend](#migrate-to-goodjob-from-a-different-activejob-backend)
|
56
56
|
- [Monitor and preserve worked jobs](#monitor-and-preserve-worked-jobs)
|
57
57
|
- [PgBouncer compatibility](#pgbouncer-compatibility)
|
58
|
+
- [CLI HTTP health check probes](#cli-http-healthcheck-probes)
|
58
59
|
- [Contribute](#contribute)
|
59
60
|
- [Gem development](#gem-development)
|
60
61
|
- [Release](#release)
|
@@ -170,6 +171,7 @@ Options:
|
|
170
171
|
[--enable-cron] # Whether to run cron process (default: false)
|
171
172
|
[--daemonize] # Run as a background daemon (default: false)
|
172
173
|
[--pidfile=PIDFILE] # Path to write daemonized Process ID (env var: GOOD_JOB_PIDFILE, default: tmp/pids/good_job.pid)
|
174
|
+
[--probe-port=PORT] # Port for http health check (env var: GOOD_JOB_PROBE_PORT, default: nil)
|
173
175
|
|
174
176
|
Executes queued jobs.
|
175
177
|
|
@@ -837,6 +839,61 @@ A workaround to this limitation is to make a direct database connection availabl
|
|
837
839
|
GoodJob.active_record_parent_class = "ApplicationDirectRecord"
|
838
840
|
```
|
839
841
|
|
842
|
+
### CLI HTTP health check probes
|
843
|
+
|
844
|
+
GoodJob's CLI offers an http health check probe to better manage process lifecycle in containerized environments like Kubernetes:
|
845
|
+
|
846
|
+
```bash
|
847
|
+
# Run the CLI with a health check on port 7001
|
848
|
+
good_job start --probe-port=7001
|
849
|
+
|
850
|
+
# or via an environment variable
|
851
|
+
GOOD_JOB_PROBE_PORT=7001 good_job start
|
852
|
+
|
853
|
+
# Probe the status
|
854
|
+
curl localhost:7001/status
|
855
|
+
curl localhost:7001/status/started
|
856
|
+
curl localhost:7001/status/connected
|
857
|
+
```
|
858
|
+
|
859
|
+
Multiple health checks are available at different paths:
|
860
|
+
|
861
|
+
- `/` or `/status`: the CLI process is running
|
862
|
+
- `/status/started`: the multithreaded job executor is running
|
863
|
+
- `/status/connected`: the database connection is established
|
864
|
+
|
865
|
+
This can be configured, for example with Kubernetes:
|
866
|
+
|
867
|
+
```yaml
|
868
|
+
spec:
|
869
|
+
containers:
|
870
|
+
- name: good_job
|
871
|
+
image: my_app:latest
|
872
|
+
env:
|
873
|
+
- name: RAILS_ENV
|
874
|
+
value: production
|
875
|
+
- name: GOOD_JOB_PROBE_PORT
|
876
|
+
value: 7001
|
877
|
+
command:
|
878
|
+
- good_job
|
879
|
+
- start
|
880
|
+
ports:
|
881
|
+
- name: probe-port
|
882
|
+
containerPort: 7001
|
883
|
+
startupProbe:
|
884
|
+
httpGet:
|
885
|
+
path: "/status/started"
|
886
|
+
port: probe-port
|
887
|
+
failureThreshold: 30
|
888
|
+
periodSeconds: 10
|
889
|
+
livenessProbe:
|
890
|
+
httpGet:
|
891
|
+
path: "/status/connected"
|
892
|
+
port: probe-port
|
893
|
+
failureThreshold: 1
|
894
|
+
periodSeconds: 10
|
895
|
+
```
|
896
|
+
|
840
897
|
## Contribute
|
841
898
|
|
842
899
|
Contributions are welcomed and appreciated 🙏
|
@@ -5,6 +5,25 @@ module GoodJob
|
|
5
5
|
|
6
6
|
around_action :switch_locale
|
7
7
|
|
8
|
+
content_security_policy do |policy|
|
9
|
+
policy.default_src(:none) if policy.default_src.blank?
|
10
|
+
policy.connect_src(:self) if policy.connect_src.blank?
|
11
|
+
policy.base_uri(:none) if policy.base_uri.blank?
|
12
|
+
policy.font_src(:self) if policy.font_src.blank?
|
13
|
+
policy.img_src(:self, :data) if policy.img_src.blank?
|
14
|
+
policy.object_src(:none) if policy.object_src.blank?
|
15
|
+
policy.script_src(:self) if policy.script_src.blank?
|
16
|
+
policy.style_src(:self) if policy.style_src.blank?
|
17
|
+
policy.form_action(:self) if policy.form_action.blank?
|
18
|
+
policy.frame_ancestors(:none) if policy.frame_ancestors.blank?
|
19
|
+
end
|
20
|
+
|
21
|
+
before_action do
|
22
|
+
next if request.content_security_policy_nonce_generator
|
23
|
+
|
24
|
+
request.content_security_policy_nonce_generator = ->(_request) { SecureRandom.base64(16) }
|
25
|
+
end
|
26
|
+
|
8
27
|
private
|
9
28
|
|
10
29
|
def switch_locale(&action)
|
data/lib/good_job/cli.rb
CHANGED
@@ -79,6 +79,9 @@ module GoodJob
|
|
79
79
|
method_option :pidfile,
|
80
80
|
type: :string,
|
81
81
|
desc: "Path to write daemonized Process ID (env var: GOOD_JOB_PIDFILE, default: tmp/pids/good_job.pid)"
|
82
|
+
method_option :probe_port,
|
83
|
+
type: :numeric,
|
84
|
+
desc: "Port for http health check (env var: GOOD_JOB_PROBE_PORT, default: nil)"
|
82
85
|
|
83
86
|
def start
|
84
87
|
set_up_application!
|
@@ -93,6 +96,10 @@ module GoodJob
|
|
93
96
|
poller.recipients << [scheduler, :create_thread]
|
94
97
|
|
95
98
|
cron_manager = GoodJob::CronManager.new(configuration.cron_entries, start_on_initialize: true) if configuration.enable_cron?
|
99
|
+
if configuration.probe_port
|
100
|
+
probe_server = GoodJob::ProbeServer.new(port: configuration.probe_port)
|
101
|
+
probe_server.start
|
102
|
+
end
|
96
103
|
|
97
104
|
@stop_good_job_executable = false
|
98
105
|
%w[INT TERM].each do |signal|
|
@@ -106,6 +113,7 @@ module GoodJob
|
|
106
113
|
|
107
114
|
executors = [notifier, poller, cron_manager, scheduler].compact
|
108
115
|
GoodJob._shutdown_all(executors, timeout: configuration.shutdown_timeout)
|
116
|
+
probe_server&.stop
|
109
117
|
end
|
110
118
|
|
111
119
|
default_task :start
|
@@ -195,6 +195,13 @@ module GoodJob
|
|
195
195
|
Rails.application.root.join('tmp', 'pids', 'good_job.pid')
|
196
196
|
end
|
197
197
|
|
198
|
+
# Port of the probe server
|
199
|
+
# @return [nil,Integer]
|
200
|
+
def probe_port
|
201
|
+
options[:probe_port] ||
|
202
|
+
env['GOOD_JOB_PROBE_PORT']
|
203
|
+
end
|
204
|
+
|
198
205
|
private
|
199
206
|
|
200
207
|
def rails_config
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module GoodJob
|
4
|
+
class ProbeServer
|
5
|
+
RACK_SERVER = 'webrick'
|
6
|
+
|
7
|
+
def self.task_observer(time, output, thread_error) # rubocop:disable Lint/UnusedMethodArgument
|
8
|
+
return if thread_error.is_a? Concurrent::CancelledOperationError
|
9
|
+
|
10
|
+
GoodJob.on_thread_error.call(thread_error) if thread_error && GoodJob.on_thread_error.respond_to?(:call)
|
11
|
+
end
|
12
|
+
|
13
|
+
def initialize(port:)
|
14
|
+
@port = port
|
15
|
+
end
|
16
|
+
|
17
|
+
def start
|
18
|
+
@handler = Rack::Handler.get(RACK_SERVER)
|
19
|
+
@future = Concurrent::Future.new(args: [@handler, @port, GoodJob.logger]) do |thr_handler, thr_port, thr_logger|
|
20
|
+
thr_handler.run(self, Port: thr_port, Logger: thr_logger, AccessLog: [])
|
21
|
+
end
|
22
|
+
@future.add_observer(self.class, :task_observer)
|
23
|
+
@future.execute
|
24
|
+
end
|
25
|
+
|
26
|
+
def running?
|
27
|
+
@handler&.instance_variable_get(:@server)&.status == :Running
|
28
|
+
end
|
29
|
+
|
30
|
+
def stop
|
31
|
+
@handler&.shutdown
|
32
|
+
@future&.value # wait for Future to exit
|
33
|
+
end
|
34
|
+
|
35
|
+
def call(env)
|
36
|
+
case Rack::Request.new(env).path
|
37
|
+
when '/', '/status'
|
38
|
+
[200, {}, ["OK"]]
|
39
|
+
when '/status/started'
|
40
|
+
started = GoodJob::Scheduler.instances.any? && GoodJob::Scheduler.instances.all?(&:running?)
|
41
|
+
started ? [200, {}, ["Started"]] : [503, {}, ["Not started"]]
|
42
|
+
when '/status/connected'
|
43
|
+
connected = GoodJob::Scheduler.instances.any? && GoodJob::Scheduler.instances.all?(&:running?) &&
|
44
|
+
GoodJob::Notifier.instances.any? && GoodJob::Notifier.instances.all?(&:listening?)
|
45
|
+
connected ? [200, {}, ["Connected"]] : [503, {}, ["Not connected"]]
|
46
|
+
else
|
47
|
+
[404, {}, ["Not found"]]
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
data/lib/good_job/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: good_job
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ben Sheldon
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-11-
|
11
|
+
date: 2021-11-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activejob
|
@@ -94,6 +94,20 @@ dependencies:
|
|
94
94
|
- - ">="
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: 0.14.1
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: webrick
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '1.3'
|
104
|
+
type: :runtime
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '1.3'
|
97
111
|
- !ruby/object:Gem::Dependency
|
98
112
|
name: zeitwerk
|
99
113
|
requirement: !ruby/object:Gem::Requirement
|
@@ -410,6 +424,7 @@ files:
|
|
410
424
|
- lib/good_job/multi_scheduler.rb
|
411
425
|
- lib/good_job/notifier.rb
|
412
426
|
- lib/good_job/poller.rb
|
427
|
+
- lib/good_job/probe_server.rb
|
413
428
|
- lib/good_job/railtie.rb
|
414
429
|
- lib/good_job/scheduler.rb
|
415
430
|
- lib/good_job/version.rb
|