good_job 0.6.0 → 0.7.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: c20439024a46084c22e46bb42e38589687c2ab2cea47d90705abc4fa042ad449
4
- data.tar.gz: e5ea8e7fa607a10fd936c62623a39d32b891ef629636e0b04fb3d36aa7ab1f3f
3
+ metadata.gz: 4f7dda29494df3fc05a199d6bf0efbc825a47653c3af507a0d1ceb92456d4307
4
+ data.tar.gz: 881ad046bab6b17c5d532d035fddef54420639288a0a4bd8f4f07b980c1fa239
5
5
  SHA512:
6
- metadata.gz: 4af34ce400c409a61892c9d35693f69e023b5dbd3d54cacfd6d9b044aaf481c616e3fdb9da53470f79919830a916a08f67550ce807eda1c59a43fa1da4092f07
7
- data.tar.gz: 81304be6bc9e6925b16fa030d2031377bd90bac894b4c8792cfe5e02ff81677bf04d476b1a3435e951a804e6d284e4d8aa7452c6090969f841dbd6e59a9c301c
6
+ metadata.gz: c0cfc3c4d61666844a6bd7c532670e0b1be40fd6f805eff63919d3600d06933b8029f0febbc81efbf52b1f3d459317caeb522affe20dde9d3f4d7672622fd708
7
+ data.tar.gz: c4c9a9fddb2108769e3672baeaeaca2f7c966ee708f95867ed57970e688debcf1ce41a3eacd65d88c0192700f1b293cd4a9ad63fee9e4af93d44934b0876120f
@@ -1,5 +1,19 @@
1
1
  # Changelog
2
2
 
3
+ ## [v0.7.0](https://github.com/bensheldon/good_job/tree/v0.7.0) (2020-07-15)
4
+
5
+ [Full Changelog](https://github.com/bensheldon/good_job/compare/v0.6.0...v0.7.0)
6
+
7
+ **Closed issues:**
8
+
9
+ - Always store a default priority \(0\) and scheduled\_at\(Time.current\) [\#30](https://github.com/bensheldon/good_job/issues/30)
10
+
11
+ **Merged pull requests:**
12
+
13
+ - Add more examples to Readme [\#39](https://github.com/bensheldon/good_job/pull/39) ([bensheldon](https://github.com/bensheldon))
14
+ - Add additional Rubocops and lint [\#38](https://github.com/bensheldon/good_job/pull/38) ([bensheldon](https://github.com/bensheldon))
15
+ - Always store a default queue\_name, priority and scheduled\_at; index by queue\_name and scheduled\_at [\#37](https://github.com/bensheldon/good_job/pull/37) ([bensheldon](https://github.com/bensheldon))
16
+
3
17
  ## [v0.6.0](https://github.com/bensheldon/good_job/tree/v0.6.0) (2020-07-15)
4
18
 
5
19
  [Full Changelog](https://github.com/bensheldon/good_job/compare/v0.5.0...v0.6.0)
data/README.md CHANGED
@@ -7,7 +7,15 @@ Inspired by [Delayed::Job](https://github.com/collectiveidea/delayed_job) and [Q
7
7
  - Stand on the shoulders of ActiveJob. For example, [exception](https://edgeguides.rubyonrails.org/active_job_basics.html#exceptions) and [retry](https://edgeguides.rubyonrails.org/active_job_basics.html#retrying-or-discarding-failed-jobs) behavior.
8
8
  - Stand on the shoulders of Ruby on Rails. For example, ActiveRecord ORM, connection pools, and [multithreaded support](https://guides.rubyonrails.org/threading_and_code_execution.html) with [Concurrent-Ruby](https://github.com/ruby-concurrency/concurrent-ruby).
9
9
  - Stand on the shoulders of Postgres. For example, Advisory Locks.
10
- - Convention over simplicity over performance.
10
+ - Convention over simplicity over performance.
11
+
12
+ GoodJob supports all ActiveJob functionality:
13
+ - Async. GoodJob has the ability to run the job in a non-blocking manner.
14
+ - Queues. Jobs may set which queue they are run in with queue_as or by using the set method.
15
+ - Delayed. GoodJob will run the job in the future through perform_later.
16
+ - Priorities. The order in which jobs are processed can be configured differently.
17
+ - Timeouts. GoodJob defers to ActiveJob where it can be implemented as an `around` hook. See [Taking advantage of ActiveJob](#taking-advantage-of-activejob).
18
+ - Retries. GoodJob will automatically retry uncompleted jobs immediately. See [Taking advantage of ActiveJob](#taking-advantage-of-activejob).
11
19
 
12
20
  ## Installation
13
21
 
@@ -43,6 +51,9 @@ $ bundle install
43
51
  t.integer :priority
44
52
  t.jsonb :serialized_params
45
53
  t.timestamp :scheduled_at
54
+
55
+ t.index :scheduled_at
56
+ t.index [:queue_name, :scheduled_at]
46
57
  end
47
58
  end
48
59
  end
@@ -73,6 +84,11 @@ $ bundle install
73
84
  config.active_job.queue_adapter = GoodJob::Adapter.new
74
85
  ```
75
86
 
87
+ 1. Queue your job 🎉:
88
+ ```ruby
89
+ YourJob.set(queue: :some_queue, wait: 5.minutes, priority: 10).perform_later
90
+ ```
91
+
76
92
  1. In production, the scheduler is designed to run in its own process:
77
93
  ```bash
78
94
  $ bundle exec good_job
@@ -90,6 +106,25 @@ $ bundle install
90
106
  # [--queues=queue1,queue2] # Queues to work from. Separate multiple queues with commas (default: *)
91
107
  # [--poll-interval=N] # Interval between polls for available jobs in seconds (default: 1)
92
108
  ```
109
+
110
+ ### Taking advantage of ActiveJob
111
+
112
+ ActiveJob has a rich set of built-in functionality for timeouts, error handling, and retrying. For example:
113
+
114
+ ```ruby
115
+ class ApplicationJob < ActiveJob::Base
116
+ # Retry errors an infinite number of times with exponential back-off
117
+ retry_on StandardError, wait: :exponentially_longer, attempts: Float::INFINITY
118
+
119
+ # Timeout jobs after 10 minutes
120
+ JobTimeoutError = Class.new(StandardError)
121
+ around_perform do |_job, block|
122
+ Timeout.timeout(10.minutes, JobTimeoutError) do
123
+ block.call
124
+ end
125
+ end
126
+ end
127
+ ```
93
128
 
94
129
  ### Configuring Job Execution Threads
95
130
 
@@ -11,7 +11,7 @@ module GoodJob
11
11
  def enqueue_at(active_job, timestamp)
12
12
  good_job = GoodJob::Job.enqueue(
13
13
  active_job,
14
- scheduled_at: timestamp ? Time.at(timestamp) : nil,
14
+ scheduled_at: timestamp ? Time.zone.at(timestamp) : nil,
15
15
  create_with_advisory_lock: inline?
16
16
  )
17
17
 
@@ -2,9 +2,12 @@ module GoodJob
2
2
  class Job < ActiveRecord::Base
3
3
  include Lockable
4
4
 
5
- self.table_name = 'good_jobs'
5
+ DEFAULT_QUEUE_NAME = 'default'.freeze
6
+ DEFAULT_PRIORITY = 0
6
7
 
7
- scope :only_scheduled, -> { where("scheduled_at < ?", Time.current).or(where(scheduled_at: nil)) }
8
+ self.table_name = 'good_jobs'.freeze
9
+
10
+ scope :only_scheduled, -> { where(arel_table['scheduled_at'].lteq(Time.current)).or(where(scheduled_at: nil)) }
8
11
  scope :priority_ordered, -> { order(priority: :desc) }
9
12
  scope :to_performer, -> { Performer.new(self) }
10
13
 
@@ -31,10 +34,10 @@ module GoodJob
31
34
  good_job = nil
32
35
  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|
33
36
  good_job = GoodJob::Job.new(
34
- queue_name: active_job.queue_name,
35
- priority: active_job.priority,
37
+ queue_name: active_job.queue_name.presence || DEFAULT_QUEUE_NAME,
38
+ priority: active_job.priority || DEFAULT_PRIORITY,
36
39
  serialized_params: active_job.serialize,
37
- scheduled_at: scheduled_at,
40
+ scheduled_at: scheduled_at || Time.current,
38
41
  create_with_advisory_lock: create_with_advisory_lock
39
42
  )
40
43
 
@@ -37,14 +37,17 @@ module GoodJob
37
37
  scope :owns_advisory_locked, -> { joins_advisory_locks.where('"pg_locks"."pid" = pg_backend_pid()') }
38
38
 
39
39
  attr_accessor :create_with_advisory_lock
40
+
40
41
  after_create -> { advisory_lock }, if: :create_with_advisory_lock
41
42
  end
42
43
 
43
44
  class_methods do
44
- def with_advisory_lock(&block)
45
+ def with_advisory_lock
46
+ raise ArgumentError, "Must provide a block" unless block_given?
47
+
45
48
  records = advisory_lock.to_a
46
49
  begin
47
- block.call(records)
50
+ yield(records)
48
51
  ensure
49
52
  records.each(&:advisory_unlock)
50
53
  end
@@ -73,6 +76,8 @@ module GoodJob
73
76
  end
74
77
 
75
78
  def with_advisory_lock
79
+ raise ArgumentError, "Must provide a block" unless block_given?
80
+
76
81
  advisory_lock!
77
82
  yield
78
83
  ensure
@@ -1,3 +1,3 @@
1
1
  module GoodJob
2
- VERSION = '0.6.0'.freeze
2
+ VERSION = '0.7.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.6.0
4
+ version: 0.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: 2020-07-15 00:00:00.000000000 Z
11
+ date: 2020-07-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby
@@ -178,6 +178,34 @@ dependencies:
178
178
  - - ">="
179
179
  - !ruby/object:Gem::Version
180
180
  version: '0'
181
+ - !ruby/object:Gem::Dependency
182
+ name: rubocop-performance
183
+ requirement: !ruby/object:Gem::Requirement
184
+ requirements:
185
+ - - ">="
186
+ - !ruby/object:Gem::Version
187
+ version: '0'
188
+ type: :development
189
+ prerelease: false
190
+ version_requirements: !ruby/object:Gem::Requirement
191
+ requirements:
192
+ - - ">="
193
+ - !ruby/object:Gem::Version
194
+ version: '0'
195
+ - !ruby/object:Gem::Dependency
196
+ name: rubocop-rails
197
+ requirement: !ruby/object:Gem::Requirement
198
+ requirements:
199
+ - - ">="
200
+ - !ruby/object:Gem::Version
201
+ version: '0'
202
+ type: :development
203
+ prerelease: false
204
+ version_requirements: !ruby/object:Gem::Requirement
205
+ requirements:
206
+ - - ">="
207
+ - !ruby/object:Gem::Version
208
+ version: '0'
181
209
  - !ruby/object:Gem::Dependency
182
210
  name: rubocop-rspec
183
211
  requirement: !ruby/object:Gem::Requirement