good_job 0.5.0 → 0.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: c11065689d3442c14ab8afb08ad17a96c45414287e9c24440d26be766eff3566
4
- data.tar.gz: 316168ca2ecf9aa9a239d007b85b589c34ec68064ad3ec376665bb893aceae4c
3
+ metadata.gz: c20439024a46084c22e46bb42e38589687c2ab2cea47d90705abc4fa042ad449
4
+ data.tar.gz: e5ea8e7fa607a10fd936c62623a39d32b891ef629636e0b04fb3d36aa7ab1f3f
5
5
  SHA512:
6
- metadata.gz: 9cb0b54f3e2a7189684fb5f3ea98ea4febd6e1651ff7f9f47b78be19e9a4948c731c9e990e89921b3763236a33cbf45905d8c05c417d5044caaf844b67600510
7
- data.tar.gz: 8f45cc0b5ccd1c61c3e55ac748359156d3f4081646537b327476bd964e15e45e6a953c01ae0f237b0c08fd7bcbd3bd94bf9d7bb484c45d26600790f7870b9ccf
6
+ metadata.gz: 4af34ce400c409a61892c9d35693f69e023b5dbd3d54cacfd6d9b044aaf481c616e3fdb9da53470f79919830a916a08f67550ce807eda1c59a43fa1da4092f07
7
+ data.tar.gz: 81304be6bc9e6925b16fa030d2031377bd90bac894b4c8792cfe5e02ff81677bf04d476b1a3435e951a804e6d284e4d8aa7452c6090969f841dbd6e59a9c301c
@@ -1,14 +1,30 @@
1
1
  # Changelog
2
2
 
3
- ## [0.5.0](https://github.com/bensheldon/good_job/tree/0.5.0) (2020-07-13)
3
+ ## [v0.6.0](https://github.com/bensheldon/good_job/tree/v0.6.0) (2020-07-15)
4
4
 
5
- [Full Changelog](https://github.com/bensheldon/good_job/compare/v0.4.0...0.5.0)
5
+ [Full Changelog](https://github.com/bensheldon/good_job/compare/v0.5.0...v0.6.0)
6
+
7
+ **Closed issues:**
8
+
9
+ - Improve the command line options [\#32](https://github.com/bensheldon/good_job/issues/32)
10
+ - Allow config.active\_job.queue\_adapter = :good\_job to work [\#5](https://github.com/bensheldon/good_job/issues/5)
6
11
 
7
12
  **Merged pull requests:**
8
13
 
9
- - Update development Ruby to 2.6.6 and gems [\#29](https://github.com/bensheldon/good_job/pull/29) ([bensheldon](https://github.com/bensheldon))
14
+ - Improve generation of changelog [\#36](https://github.com/bensheldon/good_job/pull/36) ([bensheldon](https://github.com/bensheldon))
15
+ - Update Github Action Workflow for Backlog Project Board [\#35](https://github.com/bensheldon/good_job/pull/35) ([bensheldon](https://github.com/bensheldon))
16
+ - Add configuration options to good\_job executable [\#33](https://github.com/bensheldon/good_job/pull/33) ([bensheldon](https://github.com/bensheldon))
17
+ - Extract Job querying behavior out of Scheduler [\#31](https://github.com/bensheldon/good_job/pull/31) ([bensheldon](https://github.com/bensheldon))
10
18
  - Allow configuration of Rails queue adapter with `:good\_job` [\#28](https://github.com/bensheldon/good_job/pull/28) ([bensheldon](https://github.com/bensheldon))
11
19
 
20
+ ## [v0.5.0](https://github.com/bensheldon/good_job/tree/v0.5.0) (2020-07-13)
21
+
22
+ [Full Changelog](https://github.com/bensheldon/good_job/compare/v0.4.0...v0.5.0)
23
+
24
+ **Merged pull requests:**
25
+
26
+ - Update development Ruby to 2.6.6 and gems [\#29](https://github.com/bensheldon/good_job/pull/29) ([bensheldon](https://github.com/bensheldon))
27
+
12
28
  ## [v0.4.0](https://github.com/bensheldon/good_job/tree/v0.4.0) (2020-03-31)
13
29
 
14
30
  [Full Changelog](https://github.com/bensheldon/good_job/compare/v0.3.0...v0.4.0)
@@ -46,6 +62,7 @@
46
62
 
47
63
  - Clean up Gemspec [\#15](https://github.com/bensheldon/good_job/pull/15) ([bensheldon](https://github.com/bensheldon))
48
64
  - Set up Rubocop [\#14](https://github.com/bensheldon/good_job/pull/14) ([bensheldon](https://github.com/bensheldon))
65
+ - Add pg gem as explicit dependency [\#13](https://github.com/bensheldon/good_job/pull/13) ([bensheldon](https://github.com/bensheldon))
49
66
  - Bump nokogiri from 1.10.7 to 1.10.9 [\#12](https://github.com/bensheldon/good_job/pull/12) ([dependabot[bot]](https://github.com/apps/dependabot))
50
67
  - Add Appraisal with tests for Rails 5.1, 5.2, 6.0 [\#11](https://github.com/bensheldon/good_job/pull/11) ([bensheldon](https://github.com/bensheldon))
51
68
 
@@ -55,7 +72,6 @@
55
72
 
56
73
  **Merged pull requests:**
57
74
 
58
- - Add pg gem as explicit dependency [\#13](https://github.com/bensheldon/good_job/pull/13) ([bensheldon](https://github.com/bensheldon))
59
75
  - Use Rails.logger and ActiveSupport::Notifications for logging instead of puts [\#10](https://github.com/bensheldon/good_job/pull/10) ([bensheldon](https://github.com/bensheldon))
60
76
  - Remove minitest files [\#9](https://github.com/bensheldon/good_job/pull/9) ([bensheldon](https://github.com/bensheldon))
61
77
  - Use scheduled\_at and priority for scheduling [\#8](https://github.com/bensheldon/good_job/pull/8) ([bensheldon](https://github.com/bensheldon))
data/README.md CHANGED
@@ -78,6 +78,19 @@ $ bundle install
78
78
  $ bundle exec good_job
79
79
  ```
80
80
 
81
+ Configuration options available with `help`:
82
+ ```bash
83
+ $ bundle exec good_job help start
84
+
85
+ # Usage:
86
+ # good_job start
87
+ #
88
+ # Options:
89
+ # [--max-threads=N] # Maximum number of threads to use for working jobs (default: ActiveRecord::Base.connection_pool.size)
90
+ # [--queues=queue1,queue2] # Queues to work from. Separate multiple queues with commas (default: *)
91
+ # [--poll-interval=N] # Interval between polls for available jobs in seconds (default: 1)
92
+ ```
93
+
81
94
  ### Configuring Job Execution Threads
82
95
 
83
96
  GoodJob executes enqueued jobs using threads. There is a lot than can be said about [multithreaded behavior in Ruby on Rails](https://guides.rubyonrails.org/threading_and_code_execution.html), but briefly:
@@ -136,7 +149,7 @@ Package maintainers can release this gem with the following [gem-release](https:
136
149
  $ gem signin
137
150
 
138
151
  # Update version number, changelog, and create git commit:
139
- $ bundle exec rake commit_version
152
+ $ bundle exec rake commit_version[minor] # major,minor,patch
140
153
 
141
154
  # ..and follow subsequent directions.
142
155
  ```
@@ -16,8 +16,11 @@ module GoodJob
16
16
  )
17
17
 
18
18
  if inline?
19
- good_job.perform
20
- good_job.advisory_unlock
19
+ begin
20
+ good_job.perform
21
+ ensure
22
+ good_job.advisory_unlock
23
+ end
21
24
  end
22
25
 
23
26
  good_job
@@ -4,23 +4,59 @@ module GoodJob
4
4
  class CLI < Thor
5
5
  RAILS_ENVIRONMENT_RB = File.expand_path("config/environment.rb")
6
6
 
7
- desc :start, "Start jobs"
8
- method_option :max_threads, type: :numeric
7
+ desc :start, "Start job worker"
8
+ method_option :max_threads,
9
+ type: :numeric,
10
+ desc: "Maximum number of threads to use for working jobs (default: ActiveRecord::Base.connection_pool.size)"
11
+ method_option :queues,
12
+ type: :string,
13
+ banner: "queue1,queue2",
14
+ desc: "Queues to work from. Separate multiple queues with commas (default: *)"
15
+ method_option :poll_interval,
16
+ type: :numeric,
17
+ desc: "Interval between polls for available jobs in seconds (default: 1)"
9
18
  def start
10
19
  require RAILS_ENVIRONMENT_RB
11
20
 
12
- max_threads = options[:max_threads] ||
13
- ENV['GOOD_JOB_MAX_THREADS'] ||
14
- ENV['RAILS_MAX_THREADS'] ||
15
- ActiveRecord::Base.connection_pool.size
21
+ max_threads = (
22
+ options[:max_threads] ||
23
+ ENV['GOOD_JOB_MAX_THREADS'] ||
24
+ ENV['RAILS_MAX_THREADS'] ||
25
+ ActiveRecord::Base.connection_pool.size
26
+ ).to_i
16
27
 
17
- $stdout.puts "GoodJob starting with max_threads=#{max_threads}"
18
- scheduler = GoodJob::Scheduler.new(pool_options: { max_threads: max_threads })
28
+ queue_names = (
29
+ options[:queues] ||
30
+ ENV['GOOD_JOB_QUEUES'] ||
31
+ '*'
32
+ ).split(',').map(&:strip)
19
33
 
34
+ poll_interval = (
35
+ options[:poll_interval] ||
36
+ ENV['GOOD_JOB_POLL_INTERVAL']
37
+ ).to_i
38
+
39
+ job_query = GoodJob::Job.all
40
+ queue_names_without_all = queue_names.reject { |q| q == '*' }
41
+ job_query = job_query.where(queue_name: queue_names_without_all) unless queue_names_without_all.size.zero?
42
+
43
+ job_performer = job_query.only_scheduled.priority_ordered.to_performer
44
+
45
+ $stdout.puts "GoodJob worker starting with max_threads=#{max_threads} on queues=#{queue_names.join(',')}"
46
+
47
+ timer_options = {}
48
+ timer_options[:execution_interval] = poll_interval if poll_interval.positive?
49
+
50
+ pool_options = {
51
+ max_threads: max_threads,
52
+ }
53
+
54
+ scheduler = GoodJob::Scheduler.new(job_performer, timer_options: timer_options, pool_options: pool_options)
55
+
56
+ @stop_good_job_executable = false
20
57
  %w[INT TERM].each do |signal|
21
58
  trap(signal) { @stop_good_job_executable = true }
22
59
  end
23
- @stop_good_job_executable = false
24
60
 
25
61
  Kernel.loop do
26
62
  sleep 0.1
@@ -4,6 +4,29 @@ module GoodJob
4
4
 
5
5
  self.table_name = 'good_jobs'
6
6
 
7
+ scope :only_scheduled, -> { where("scheduled_at < ?", Time.current).or(where(scheduled_at: nil)) }
8
+ scope :priority_ordered, -> { order(priority: :desc) }
9
+ scope :to_performer, -> { Performer.new(self) }
10
+
11
+ class Performer
12
+ def initialize(query)
13
+ @query = query
14
+ end
15
+
16
+ def next
17
+ good_job = nil
18
+
19
+ @query.limit(1).with_advisory_lock do |good_jobs|
20
+ good_job = good_jobs.first
21
+ break unless good_job
22
+
23
+ good_job.perform
24
+ end
25
+
26
+ good_job
27
+ end
28
+ end
29
+
7
30
  def self.enqueue(active_job, scheduled_at: nil, create_with_advisory_lock: false)
8
31
  good_job = nil
9
32
  ActiveSupport::Notifications.instrument("enqueue_job.good_job", { active_job: active_job, scheduled_at: scheduled_at, create_with_advisory_lock: create_with_advisory_lock }) do |instrument_payload|
@@ -20,9 +20,10 @@ module GoodJob
20
20
  fallback_policy: :abort, # shouldn't matter -- 0 max queue
21
21
  }.freeze
22
22
 
23
- def initialize(query = GoodJob::Job.all, timer_options: {}, pool_options: {})
24
- @query = query
23
+ def initialize(performer, timer_options: {}, pool_options: {})
24
+ raise ArgumentError, "Performer argument must implement #next" unless performer.respond_to?(:next)
25
25
 
26
+ @performer = performer
26
27
  @pool = Concurrent::ThreadPoolExecutor.new(DEFAULT_POOL_OPTIONS.merge(pool_options))
27
28
  @timer = Concurrent::TimerTask.new(DEFAULT_TIMER_OPTIONS.merge(timer_options)) do
28
29
  idle_threads = @pool.max_length - @pool.length
@@ -32,10 +33,6 @@ module GoodJob
32
33
  @timer.execute
33
34
  end
34
35
 
35
- def ordered_query
36
- @query.where("scheduled_at < ?", Time.current).or(@query.where(scheduled_at: nil)).order(priority: :desc)
37
- end
38
-
39
36
  def execute
40
37
  end
41
38
 
@@ -61,19 +58,10 @@ module GoodJob
61
58
  end
62
59
 
63
60
  def create_thread
64
- future = Concurrent::Future.new(args: [ordered_query], executor: @pool) do |query|
65
- good_job = nil
66
-
67
- Rails.application.executor.wrap do
68
- query.limit(1).with_advisory_lock do |good_jobs|
69
- good_job = good_jobs.first
70
- break unless good_job
71
-
72
- good_job.perform
73
- end
74
- end
75
-
76
- good_job
61
+ future = Concurrent::Future.new(args: [@performer], executor: @pool) do |performer|
62
+ result = nil
63
+ Rails.application.executor.wrap { result = performer.next }
64
+ result
77
65
  end
78
66
  future.add_observer(self, :task_observer)
79
67
  future.execute
@@ -83,9 +71,9 @@ module GoodJob
83
71
  ActiveSupport::Notifications.instrument("finished_timer_task.good_job", { result: executed_task, error: error, time: time })
84
72
  end
85
73
 
86
- def task_observer(time, performed_job, error)
87
- ActiveSupport::Notifications.instrument("finished_job_task.good_job", { good_job: performed_job, error: error, time: time })
88
- create_thread if performed_job
74
+ def task_observer(time, result, error)
75
+ ActiveSupport::Notifications.instrument("finished_job_task.good_job", { result: result, error: error, time: time })
76
+ create_thread if result
89
77
  end
90
78
  end
91
79
  end
@@ -1,3 +1,3 @@
1
1
  module GoodJob
2
- VERSION = '0.5.0'.freeze
2
+ VERSION = '0.6.0'.freeze
3
3
  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: 0.5.0
4
+ version: 0.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: 2020-07-13 00:00:00.000000000 Z
11
+ date: 2020-07-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby