good_job 1.5.0 → 1.6.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: 89ef994e63adf5fe8dcbcdd230d9669d21c2cb6d9c62da622c8d8a197fcb3cef
4
- data.tar.gz: 6ed6d2cc6f75c5b4dc6976f3e360a5aeb27e3488fbd8035d086058b40d693025
3
+ metadata.gz: b8f0f56838ed9baa984ad7b70ece1c72009369149bb45522aa140298ff727d44
4
+ data.tar.gz: a076e6f1315911e9fcacc8be7be4e87d176f6a63fd4cf8e297b8985d928074cf
5
5
  SHA512:
6
- metadata.gz: f8d856f3797236bffecfffe5bcb58599aa0b2f843962fe09032eb0606d432d1f379dd564d00e29512bd6e3ca0c26c261401eed4b45806f21c660d9cd1a9a4838
7
- data.tar.gz: cd223dc763e1bb56d746f957aec29403ed78b6d89619fd4d4b23148d2f78a86c452e29e48249cf408cc4fff7c0ee564eb7032d9b02b24239a2d0215f40df5194
6
+ metadata.gz: 6eae147e6a6f22da09c87b246735d0844e09dbaaea2e9b2cc92664ad86efef95feb8572ddafa83964009572d5c55db5eefc9f589d63820fb77fc59ec8ac4f110
7
+ data.tar.gz: 3f884573f31e65c3d63c2b864a820b9e9dd5db2a71405f3514ffdd774458bb89c7b5a834878aba2a57b988cce02443fc2df8e986d09815f98784bdaa9de6b62f
@@ -1,6 +1,25 @@
1
1
  # Changelog
2
2
 
3
- ## [v1.5.0](https://github.com/bensheldon/good_job/tree/v1.5.0) (2021-01-17)
3
+ ## [v1.6.0](https://github.com/bensheldon/good_job/tree/v1.6.0) (2021-01-21)
4
+
5
+ [Full Changelog](https://github.com/bensheldon/good_job/compare/v1.5.0...v1.6.0)
6
+
7
+ **Implemented enhancements:**
8
+
9
+ - Running as a daemon [\#88](https://github.com/bensheldon/good_job/issues/88)
10
+ - Add daemonize option to CLI [\#202](https://github.com/bensheldon/good_job/pull/202) ([bensheldon](https://github.com/bensheldon))
11
+
12
+ **Closed issues:**
13
+
14
+ - Rails 6.1 & async - `queue\_parser': undefined method `first' for "\*":String \(NoMethodError\) [\#195](https://github.com/bensheldon/good_job/issues/195)
15
+
16
+ **Merged pull requests:**
17
+
18
+ - Add scripts directory for benchmarking and dev tasks [\#204](https://github.com/bensheldon/good_job/pull/204) ([bensheldon](https://github.com/bensheldon))
19
+ - Fix YARD attr\_ declarations for documentation [\#203](https://github.com/bensheldon/good_job/pull/203) ([bensheldon](https://github.com/bensheldon))
20
+ - Remove Appraisal gemfile locks [\#201](https://github.com/bensheldon/good_job/pull/201) ([bensheldon](https://github.com/bensheldon))
21
+
22
+ ## [v1.5.0](https://github.com/bensheldon/good_job/tree/v1.5.0) (2021-01-18)
4
23
 
5
24
  [Full Changelog](https://github.com/bensheldon/good_job/compare/v1.4.1...v1.5.0)
6
25
 
@@ -41,7 +60,6 @@
41
60
 
42
61
  **Implemented enhancements:**
43
62
 
44
- - Format serialized params to ease reading [\#170](https://github.com/bensheldon/good_job/pull/170) ([morgoth](https://github.com/morgoth))
45
63
  - Add JRuby support [\#167](https://github.com/bensheldon/good_job/pull/167) ([bensheldon](https://github.com/bensheldon))
46
64
 
47
65
  ## [v1.3.6](https://github.com/bensheldon/good_job/tree/v1.3.6) (2020-12-30)
@@ -117,6 +135,7 @@
117
135
  **Implemented enhancements:**
118
136
 
119
137
  - Extract polling from scheduler into Polling object [\#128](https://github.com/bensheldon/good_job/issues/128)
138
+ - Format serialized params to ease reading [\#170](https://github.com/bensheldon/good_job/pull/170) ([morgoth](https://github.com/morgoth))
120
139
 
121
140
  **Fixed bugs:**
122
141
 
data/README.md CHANGED
@@ -152,6 +152,8 @@ Options:
152
152
  [--max-threads=COUNT] # Maximum number of threads to use for working jobs. (env var: GOOD_JOB_MAX_THREADS, default: 5)
153
153
  [--queues=QUEUE_LIST] # Queues to work from. (env var: GOOD_JOB_QUEUES, default: *)
154
154
  [--poll-interval=SECONDS] # Interval between polls for available jobs in seconds (env var: GOOD_JOB_POLL_INTERVAL, default: 1)
155
+ [--daemonize] # Run as a background daemon (default: false)
156
+ [--pidfile=PIDFILE] # Path to write daemonized Process ID (env var: GOOD_JOB_PIDFILE, default: tmp/pids/good_job.pid)
155
157
 
156
158
  Executes queued jobs.
157
159
 
@@ -159,6 +161,7 @@ All options can be configured with environment variables.
159
161
  See option descriptions for the matching environment variable name.
160
162
 
161
163
  == Configuring queues
164
+
162
165
  Separate multiple queues with commas; exclude queues with a leading minus;
163
166
  separate isolated execution pools with semicolons and threads with colons.
164
167
  ```
@@ -15,6 +15,11 @@ module GoodJob
15
15
  # Requiring this loads the application's configuration and classes.
16
16
  RAILS_ENVIRONMENT_RB = File.expand_path("config/environment.rb")
17
17
 
18
+ # @!visibility private
19
+ def self.exit_on_failure?
20
+ true
21
+ end
22
+
18
23
  # @!macro thor.desc
19
24
  # @!method $1
20
25
  # @return [void]
@@ -27,7 +32,8 @@ module GoodJob
27
32
  See option descriptions for the matching environment variable name.
28
33
 
29
34
  == Configuring queues
30
- \x5Separate multiple queues with commas; exclude queues with a leading minus;
35
+
36
+ Separate multiple queues with commas; exclude queues with a leading minus;
31
37
  separate isolated execution pools with semicolons and threads with colons.
32
38
 
33
39
  DESCRIPTION
@@ -43,10 +49,18 @@ module GoodJob
43
49
  type: :numeric,
44
50
  banner: 'SECONDS',
45
51
  desc: "Interval between polls for available jobs in seconds (env var: GOOD_JOB_POLL_INTERVAL, default: 5)"
52
+ method_option :daemonize,
53
+ type: :boolean,
54
+ desc: "Run as a background daemon (default: false)"
55
+ method_option :pidfile,
56
+ type: :string,
57
+ desc: "Path to write daemonized Process ID (env var: GOOD_JOB_PIDFILE, default: tmp/pids/good_job.pid)"
46
58
  def start
47
59
  set_up_application!
48
60
  configuration = GoodJob::Configuration.new(options)
49
61
 
62
+ Daemon.new(pidfile: configuration.pidfile).daemonize if configuration.daemonize?
63
+
50
64
  notifier = GoodJob::Notifier.new
51
65
  poller = GoodJob::Poller.new(poll_interval: configuration.poll_interval)
52
66
  scheduler = GoodJob::Scheduler.from_configuration(configuration)
@@ -12,16 +12,15 @@ module GoodJob
12
12
  # Default number of seconds to preserve jobs for {CLI#cleanup_preserved_jobs}
13
13
  DEFAULT_CLEANUP_PRESERVED_JOBS_BEFORE_SECONDS_AGO = 24 * 60 * 60
14
14
 
15
- # @!attribute [r] options
16
- # The options that were explicitly set when initializing +Configuration+.
17
- # @return [Hash]
18
- #
19
- # @!attribute [r] env
20
- # The environment from which to read GoodJob's environment variables. By
21
- # default, this is the current process's environment, but it can be set
22
- # to something else in {#initialize}.
23
- # @return [Hash]
24
- attr_reader :options, :env
15
+ # The options that were explicitly set when initializing +Configuration+.
16
+ # @return [Hash]
17
+ attr_reader :options
18
+
19
+ # The environment from which to read GoodJob's environment variables. By
20
+ # default, this is the current process's environment, but it can be set
21
+ # to something else in {#initialize}.
22
+ # @return [Hash]
23
+ attr_reader :env
25
24
 
26
25
  # @param options [Hash] Any explicitly specified configuration options to
27
26
  # use. Keys are symbols that match the various methods on this class.
@@ -108,7 +107,7 @@ module GoodJob
108
107
 
109
108
  # Number of seconds to preserve jobs when using the +good_job cleanup_preserved_jobs+ CLI command.
110
109
  # This configuration is only used when {GoodJob.preserve_job_records} is +true+.
111
- # @return [Boolean]
110
+ # @return [Integer]
112
111
  def cleanup_preserved_jobs_before_seconds_ago
113
112
  (
114
113
  options[:before_seconds_ago] ||
@@ -118,6 +117,20 @@ module GoodJob
118
117
  ).to_i
119
118
  end
120
119
 
120
+ # Tests whether to daemonize the process.
121
+ # @return [Boolean]
122
+ def daemonize?
123
+ options[:daemonize] || false
124
+ end
125
+
126
+ # Path of the pidfile to create when running as a daemon.
127
+ # @return [Pathname,String]
128
+ def pidfile
129
+ options[:pidfile] ||
130
+ env['GOOD_JOB_PIDFILE'] ||
131
+ Rails.application.root.join('tmp', 'pids', 'good_job.pid')
132
+ end
133
+
121
134
  private
122
135
 
123
136
  def rails_config
@@ -0,0 +1,59 @@
1
+ module GoodJob
2
+ #
3
+ # Manages daemonization of the current process.
4
+ #
5
+ class Daemon
6
+ # The path of the generated pidfile.
7
+ # @return [Pathname,String]
8
+ attr_reader :pidfile
9
+
10
+ # @param pidfile [Pathname,String] Pidfile path
11
+ def initialize(pidfile:)
12
+ @pidfile = pidfile
13
+ end
14
+
15
+ # Daemonizes the current process and writes out a pidfile.
16
+ def daemonize
17
+ check_pid
18
+ Process.daemon
19
+ write_pid
20
+ end
21
+
22
+ private
23
+
24
+ def write_pid
25
+ File.open(pidfile, ::File::CREAT | ::File::EXCL | ::File::WRONLY) { |f| f.write(Process.pid.to_s) }
26
+ at_exit { File.delete(pidfile) if File.exist?(pidfile) }
27
+ rescue Errno::EEXIST
28
+ check_pid
29
+ retry
30
+ end
31
+
32
+ def delete_pid
33
+ File.delete(pidfile) if File.exist?(pidfile)
34
+ end
35
+
36
+ def check_pid
37
+ case pid_status(pidfile)
38
+ when :running, :not_owned
39
+ abort "A server is already running. Check #{pidfile}"
40
+ when :dead
41
+ File.delete(pidfile)
42
+ end
43
+ end
44
+
45
+ def pid_status(pidfile)
46
+ return :exited unless File.exist?(pidfile)
47
+
48
+ pid = ::File.read(pidfile).to_i
49
+ return :dead if pid.zero?
50
+
51
+ Process.kill(0, pid) # check process status
52
+ :running
53
+ rescue Errno::ESRCH
54
+ :dead
55
+ rescue Errno::EPERM
56
+ :not_owned
57
+ end
58
+ end
59
+ end
@@ -92,8 +92,6 @@ module GoodJob
92
92
  # @return [ActiveRecord::Relation]
93
93
  scope :owns_advisory_locked, -> { joins_advisory_locks.where('"pg_locks"."pid" = pg_backend_pid()') }
94
94
 
95
- # @!attribute [r] create_with_advisory_lock
96
- # @return [Boolean]
97
95
  # Whether an advisory lock should be acquired in the same transaction
98
96
  # that created the record.
99
97
  #
@@ -107,6 +105,8 @@ module GoodJob
107
105
  # record = MyLockableRecord.create(create_with_advisory_lock: true)
108
106
  # record.advisory_locked?
109
107
  # => true
108
+ #
109
+ # @return [Boolean]
110
110
  attr_accessor :create_with_advisory_lock
111
111
 
112
112
  after_create -> { advisory_lock }, if: :create_with_advisory_lock
@@ -8,7 +8,7 @@ module GoodJob # :nodoc:
8
8
  # periodically checking for available tasks, executing tasks within a thread,
9
9
  # and efficiently scaling active threads.
10
10
  #
11
- # Every scheduler has a single {Performer} that will execute tasks.
11
+ # Every scheduler has a single {JobPerformer} that will execute tasks.
12
12
  # The scheduler is responsible for calling its performer efficiently across threads managed by an instance of +Concurrent::ThreadPoolExecutor+.
13
13
  # If a performer does not have work, the thread will go to sleep.
14
14
  # The scheduler maintains an instance of +Concurrent::TimerTask+, which wakes sleeping threads and causes them to check whether the performer has new work.
@@ -1,4 +1,4 @@
1
1
  module GoodJob
2
2
  # GoodJob gem version.
3
- VERSION = '1.5.0'.freeze
3
+ VERSION = '1.6.0'.freeze
4
4
  end
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: 1.5.0
4
+ version: 1.6.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-01-18 00:00:00.000000000 Z
11
+ date: 2021-01-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activejob
@@ -357,6 +357,7 @@ files:
357
357
  - lib/good_job/cli.rb
358
358
  - lib/good_job/configuration.rb
359
359
  - lib/good_job/current_execution.rb
360
+ - lib/good_job/daemon.rb
360
361
  - lib/good_job/job.rb
361
362
  - lib/good_job/job_performer.rb
362
363
  - lib/good_job/lockable.rb