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 +4 -4
- data/CHANGELOG.md +14 -0
- data/README.md +36 -1
- data/lib/good_job/adapter.rb +1 -1
- data/lib/good_job/job.rb +8 -5
- data/lib/good_job/lockable.rb +7 -2
- data/lib/good_job/version.rb +1 -1
- metadata +30 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4f7dda29494df3fc05a199d6bf0efbc825a47653c3af507a0d1ceb92456d4307
|
4
|
+
data.tar.gz: 881ad046bab6b17c5d532d035fddef54420639288a0a4bd8f4f07b980c1fa239
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c0cfc3c4d61666844a6bd7c532670e0b1be40fd6f805eff63919d3600d06933b8029f0febbc81efbf52b1f3d459317caeb522affe20dde9d3f4d7672622fd708
|
7
|
+
data.tar.gz: c4c9a9fddb2108769e3672baeaeaca2f7c966ee708f95867ed57970e688debcf1ce41a3eacd65d88c0192700f1b293cd4a9ad63fee9e4af93d44934b0876120f
|
data/CHANGELOG.md
CHANGED
@@ -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
|
|
data/lib/good_job/adapter.rb
CHANGED
@@ -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
|
|
data/lib/good_job/job.rb
CHANGED
@@ -2,9 +2,12 @@ module GoodJob
|
|
2
2
|
class Job < ActiveRecord::Base
|
3
3
|
include Lockable
|
4
4
|
|
5
|
-
|
5
|
+
DEFAULT_QUEUE_NAME = 'default'.freeze
|
6
|
+
DEFAULT_PRIORITY = 0
|
6
7
|
|
7
|
-
|
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
|
|
data/lib/good_job/lockable.rb
CHANGED
@@ -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
|
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
|
-
|
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
|
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: 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-
|
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
|