good_job 0.8.1 → 1.0.2
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 +67 -3
- data/README.md +29 -23
- data/lib/generators/good_job/install_generator.rb +24 -0
- data/lib/generators/good_job/templates/migration.rb.erb +20 -0
- data/lib/good_job.rb +3 -1
- data/lib/good_job/cli.rb +19 -1
- data/lib/good_job/job.rb +57 -16
- data/lib/good_job/performer.rb +12 -0
- data/lib/good_job/scheduler.rb +27 -14
- data/lib/good_job/version.rb +1 -1
- metadata +7 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f7c64e8766a52e6bbbb5e55b409bb0100e54790d6d88340893e61f930cbf8b9e
|
4
|
+
data.tar.gz: 7e89b7bf2d3aaa45cc5b07deab36f5334a61cac44c0aec06206ddbd6eb0ebc22
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 944b64f713ad584b56fe386dc63aa6afc0538e498cff4fb46aec9098306b7e436a3d29cebd968157f34e62c9b1b0ce932e15967b4a631f9f04c60ca43d77f4c8
|
7
|
+
data.tar.gz: 5000ffc97bc381cb94999478c1fe90202b681d5cf87d697f4700cc60b94a7417fd67ca3f5428c4b50acb195bde7850a3a5d809e32c5baaf08ae3a58a2101624a
|
data/CHANGELOG.md
CHANGED
@@ -1,17 +1,81 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
-
## [
|
3
|
+
## [v1.0.2](https://github.com/bensheldon/good_job/tree/v1.0.2) (2020-07-24)
|
4
4
|
|
5
|
-
[Full Changelog](https://github.com/bensheldon/good_job/compare/
|
5
|
+
[Full Changelog](https://github.com/bensheldon/good_job/compare/v1.0.1...v1.0.2)
|
6
|
+
|
7
|
+
**Fixed bugs:**
|
8
|
+
|
9
|
+
- Fix counting of available execution threads [\#58](https://github.com/bensheldon/good_job/pull/58) ([bensheldon](https://github.com/bensheldon))
|
6
10
|
|
7
11
|
**Closed issues:**
|
8
12
|
|
9
|
-
-
|
13
|
+
- repeating/recurring jobs [\#53](https://github.com/bensheldon/good_job/issues/53)
|
14
|
+
|
15
|
+
**Merged pull requests:**
|
16
|
+
|
17
|
+
- Add migration generator [\#56](https://github.com/bensheldon/good_job/pull/56) ([thedanbob](https://github.com/thedanbob))
|
18
|
+
- Fix migration script in readme [\#55](https://github.com/bensheldon/good_job/pull/55) ([thedanbob](https://github.com/thedanbob))
|
19
|
+
|
20
|
+
## [v1.0.1](https://github.com/bensheldon/good_job/tree/v1.0.1) (2020-07-22)
|
21
|
+
|
22
|
+
[Full Changelog](https://github.com/bensheldon/good_job/compare/v1.0.0...v1.0.1)
|
23
|
+
|
24
|
+
**Merged pull requests:**
|
25
|
+
|
26
|
+
- Change threadpool idletime default to 60 seconds from 0 [\#49](https://github.com/bensheldon/good_job/pull/49) ([bensheldon](https://github.com/bensheldon))
|
27
|
+
|
28
|
+
## [v1.0.0](https://github.com/bensheldon/good_job/tree/v1.0.0) (2020-07-20)
|
29
|
+
|
30
|
+
[Full Changelog](https://github.com/bensheldon/good_job/compare/v0.9.0...v1.0.0)
|
31
|
+
|
32
|
+
## [v0.9.0](https://github.com/bensheldon/good_job/tree/v0.9.0) (2020-07-20)
|
33
|
+
|
34
|
+
[Full Changelog](https://github.com/bensheldon/good_job/compare/v0.8.2...v0.9.0)
|
35
|
+
|
36
|
+
**Merged pull requests:**
|
37
|
+
|
38
|
+
- Allow preservation of finished job records [\#46](https://github.com/bensheldon/good_job/pull/46) ([bensheldon](https://github.com/bensheldon))
|
39
|
+
|
40
|
+
## [v0.8.2](https://github.com/bensheldon/good_job/tree/v0.8.2) (2020-07-18)
|
41
|
+
|
42
|
+
[Full Changelog](https://github.com/bensheldon/good_job/compare/v0.8.1...v0.8.2)
|
43
|
+
|
44
|
+
**Closed issues:**
|
45
|
+
|
46
|
+
- Add a job timeout configuration to time out jobs that have run too long [\#19](https://github.com/bensheldon/good_job/issues/19)
|
47
|
+
|
48
|
+
**Merged pull requests:**
|
49
|
+
|
50
|
+
- Run Github Action tests on PRs from forks [\#44](https://github.com/bensheldon/good_job/pull/44) ([bensheldon](https://github.com/bensheldon))
|
51
|
+
- Fix Rubygems homepage URL [\#43](https://github.com/bensheldon/good_job/pull/43) ([joshmn](https://github.com/joshmn))
|
52
|
+
|
53
|
+
## [v0.8.1](https://github.com/bensheldon/good_job/tree/v0.8.1) (2020-07-18)
|
54
|
+
|
55
|
+
[Full Changelog](https://github.com/bensheldon/good_job/compare/v0.8.0...v0.8.1)
|
10
56
|
|
11
57
|
**Merged pull requests:**
|
12
58
|
|
13
59
|
- Move where\(scheduled\_at: Time.current\) into dynamic part of GoodJob::Job::Performer [\#42](https://github.com/bensheldon/good_job/pull/42) ([bensheldon](https://github.com/bensheldon))
|
60
|
+
|
61
|
+
## [v0.8.0](https://github.com/bensheldon/good_job/tree/v0.8.0) (2020-07-17)
|
62
|
+
|
63
|
+
[Full Changelog](https://github.com/bensheldon/good_job/compare/v0.7.0...v0.8.0)
|
64
|
+
|
65
|
+
**Merged pull requests:**
|
66
|
+
|
14
67
|
- Replace Adapter inline boolean kwarg with execution\_mode instead [\#41](https://github.com/bensheldon/good_job/pull/41) ([bensheldon](https://github.com/bensheldon))
|
68
|
+
|
69
|
+
## [v0.7.0](https://github.com/bensheldon/good_job/tree/v0.7.0) (2020-07-16)
|
70
|
+
|
71
|
+
[Full Changelog](https://github.com/bensheldon/good_job/compare/v0.6.0...v0.7.0)
|
72
|
+
|
73
|
+
**Closed issues:**
|
74
|
+
|
75
|
+
- Always store a default priority \(0\) and scheduled\_at\(Time.current\) [\#30](https://github.com/bensheldon/good_job/issues/30)
|
76
|
+
|
77
|
+
**Merged pull requests:**
|
78
|
+
|
15
79
|
- Add more examples to Readme [\#39](https://github.com/bensheldon/good_job/pull/39) ([bensheldon](https://github.com/bensheldon))
|
16
80
|
- Add additional Rubocops and lint [\#38](https://github.com/bensheldon/good_job/pull/38) ([bensheldon](https://github.com/bensheldon))
|
17
81
|
- 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))
|
data/README.md
CHANGED
@@ -9,6 +9,8 @@ GoodJob is a multithreaded, Postgres-based, ActiveJob backend for Ruby on Rails.
|
|
9
9
|
- **Backed by Postgres.** Relies upon Postgres integrity and session-level Advisory Locks to provide run-once safety and stay within the limits of `schema.rb`.
|
10
10
|
- **For most workloads.** Targets full-stack teams, economy-minded solo developers, and applications that enqueue less than 1-million jobs/day.
|
11
11
|
|
12
|
+
For more of the story of GoodJob, read the [introductory blog post](https://island94.org/2020/07/introducing-goodjob-1-0).
|
13
|
+
|
12
14
|
## Installation
|
13
15
|
|
14
16
|
Add this line to your application's Gemfile:
|
@@ -26,31 +28,9 @@ $ bundle install
|
|
26
28
|
|
27
29
|
1. Create a database migration:
|
28
30
|
```bash
|
29
|
-
$ bin/rails g
|
31
|
+
$ bin/rails g good_job:install
|
30
32
|
```
|
31
33
|
|
32
|
-
Add to the newly created migration file:
|
33
|
-
|
34
|
-
```ruby
|
35
|
-
class CreateGoodJobs < ActiveRecord::Migration[6.0]
|
36
|
-
def change
|
37
|
-
enable_extension 'pgcrypto'
|
38
|
-
|
39
|
-
create_table :good_jobs, id: :uuid do |t|
|
40
|
-
t.timestamps
|
41
|
-
|
42
|
-
t.text :queue_name
|
43
|
-
t.integer :priority
|
44
|
-
t.jsonb :serialized_params
|
45
|
-
t.timestamp :scheduled_at
|
46
|
-
|
47
|
-
t.index :scheduled_at
|
48
|
-
t.index [:queue_name, :scheduled_at]
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
52
|
-
```
|
53
|
-
|
54
34
|
Run the migration:
|
55
35
|
|
56
36
|
```bash
|
@@ -152,6 +132,32 @@ If your application is already using an ActiveJob backend, you will need to inst
|
|
152
132
|
|
153
133
|
1. Once you are confident that no unperformed jobs remain in the previous ActiveJob backend, code and configuration for that backend can be completely removed.
|
154
134
|
|
135
|
+
### Monitoring and preserving worked jobs
|
136
|
+
|
137
|
+
GoodJob is fully instrumented with [`ActiveSupport::Notifications`](https://edgeguides.rubyonrails.org/active_support_instrumentation.html#introduction-to-instrumentation).
|
138
|
+
|
139
|
+
By default, GoodJob will delete job records after they are run, regardless of whether they succeed or not (raising a kind of `StandardError`), unless they are interrupted (raising a kind of `Exception`).
|
140
|
+
|
141
|
+
To preserve job records for later inspection, set an initializer:
|
142
|
+
|
143
|
+
```ruby
|
144
|
+
# config/initializers/good_job.rb
|
145
|
+
GoodJob.preserve_job_records = true
|
146
|
+
```
|
147
|
+
|
148
|
+
It is also necessary to delete these preserved jobs from the database after a certain time period:
|
149
|
+
|
150
|
+
- For example, in a Rake task:
|
151
|
+
|
152
|
+
```ruby
|
153
|
+
# GoodJob::Job.finished(1.day.ago).delete_all
|
154
|
+
```
|
155
|
+
- For example, using the `good_job` command-line utility:
|
156
|
+
|
157
|
+
```bash
|
158
|
+
$ bundle exec good_job cleanup_preserved_jobs --before-seconds-ago=86400
|
159
|
+
```
|
160
|
+
|
155
161
|
## Development
|
156
162
|
|
157
163
|
To run tests:
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'rails/generators'
|
2
|
+
require 'rails/generators/active_record'
|
3
|
+
|
4
|
+
module GoodJob
|
5
|
+
class InstallGenerator < Rails::Generators::Base
|
6
|
+
include Rails::Generators::Migration
|
7
|
+
|
8
|
+
class << self
|
9
|
+
delegate :next_migration_number, to: ActiveRecord::Generators::Base
|
10
|
+
end
|
11
|
+
|
12
|
+
source_paths << File.join(File.dirname(__FILE__), "templates")
|
13
|
+
|
14
|
+
def create_migration_file
|
15
|
+
migration_template 'migration.rb.erb', 'db/migrate/create_good_jobs.rb', migration_version: migration_version
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def migration_version
|
21
|
+
"[#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}]"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
class CreateGoodJobs < ActiveRecord::Migration<%= migration_version %>
|
2
|
+
def change
|
3
|
+
enable_extension 'pgcrypto'
|
4
|
+
|
5
|
+
create_table :good_jobs, id: :uuid do |t|
|
6
|
+
t.text :queue_name
|
7
|
+
t.integer :priority
|
8
|
+
t.jsonb :serialized_params
|
9
|
+
t.timestamp :scheduled_at
|
10
|
+
t.timestamp :performed_at
|
11
|
+
t.timestamp :finished_at
|
12
|
+
t.text :error
|
13
|
+
|
14
|
+
t.timestamps
|
15
|
+
end
|
16
|
+
|
17
|
+
add_index :good_jobs, :scheduled_at, where: "(finished_at IS NULL)"
|
18
|
+
add_index :good_jobs, [:queue_name, :scheduled_at], where: "(finished_at IS NULL)"
|
19
|
+
end
|
20
|
+
end
|
data/lib/good_job.rb
CHANGED
@@ -4,13 +4,15 @@ require 'good_job/railtie'
|
|
4
4
|
require 'good_job/logging'
|
5
5
|
require 'good_job/lockable'
|
6
6
|
require 'good_job/job'
|
7
|
-
require
|
7
|
+
require 'good_job/scheduler'
|
8
8
|
require 'good_job/adapter'
|
9
9
|
require 'good_job/pg_locks'
|
10
|
+
require 'good_job/performer'
|
10
11
|
|
11
12
|
require 'active_job/queue_adapters/good_job_adapter'
|
12
13
|
|
13
14
|
module GoodJob
|
15
|
+
mattr_accessor :preserve_job_records, default: false
|
14
16
|
include Logging
|
15
17
|
|
16
18
|
ActiveSupport.run_load_hooks(:good_job, self)
|
data/lib/good_job/cli.rb
CHANGED
@@ -40,7 +40,12 @@ module GoodJob
|
|
40
40
|
queue_names_without_all = queue_names.reject { |q| q == '*' }
|
41
41
|
job_query = job_query.where(queue_name: queue_names_without_all) unless queue_names_without_all.size.zero?
|
42
42
|
|
43
|
-
|
43
|
+
performer_method = if GoodJob.preserve_job_records
|
44
|
+
:perform_with_advisory_lock_and_preserve_job_records
|
45
|
+
else
|
46
|
+
:perform_with_advisory_lock_and_destroy_job_records
|
47
|
+
end
|
48
|
+
job_performer = GoodJob::Performer.new(job_query, performer_method)
|
44
49
|
|
45
50
|
$stdout.puts "GoodJob worker starting with max_threads=#{max_threads} on queues=#{queue_names.join(',')}"
|
46
51
|
|
@@ -68,6 +73,19 @@ module GoodJob
|
|
68
73
|
$stdout.puts "GoodJob's jobs finished, exiting..."
|
69
74
|
end
|
70
75
|
|
76
|
+
desc :cleanup_preserved_jobs, "Delete preserved job records"
|
77
|
+
method_option :before_seconds_ago,
|
78
|
+
type: :numeric,
|
79
|
+
default: 24 * 60 * 60,
|
80
|
+
desc: "Delete records finished more than this many seconds ago"
|
81
|
+
def cleanup_preserved_jobs
|
82
|
+
require RAILS_ENVIRONMENT_RB
|
83
|
+
|
84
|
+
timestamp = Time.current - options[:before_seconds_ago]
|
85
|
+
result = GoodJob::Job.finished(timestamp).delete_all
|
86
|
+
$stdout.puts "Deleted #{result} preserved #{'job'.pluralize(result)} finished before #{timestamp}."
|
87
|
+
end
|
88
|
+
|
71
89
|
default_task :start
|
72
90
|
end
|
73
91
|
end
|
data/lib/good_job/job.rb
CHANGED
@@ -2,32 +2,46 @@ module GoodJob
|
|
2
2
|
class Job < ActiveRecord::Base
|
3
3
|
include Lockable
|
4
4
|
|
5
|
+
PreviouslyPerformedError = Class.new(StandardError)
|
6
|
+
|
5
7
|
DEFAULT_QUEUE_NAME = 'default'.freeze
|
6
8
|
DEFAULT_PRIORITY = 0
|
7
9
|
|
8
10
|
self.table_name = 'good_jobs'.freeze
|
9
11
|
|
12
|
+
scope :unfinished, (lambda do
|
13
|
+
if column_names.include?('finished_at')
|
14
|
+
where(finished_at: nil)
|
15
|
+
else
|
16
|
+
ActiveSupport::Deprecation.warn('GoodJob expects a good_jobs.finished_at column to exist. Please see the GoodJob README.md for migration instructions.')
|
17
|
+
nil
|
18
|
+
end
|
19
|
+
end)
|
10
20
|
scope :only_scheduled, -> { where(arel_table['scheduled_at'].lteq(Time.current)).or(where(scheduled_at: nil)) }
|
11
21
|
scope :priority_ordered, -> { order(priority: :desc) }
|
12
|
-
scope :
|
22
|
+
scope :finished, ->(timestamp = nil) { timestamp ? where(arel_table['finished_at'].lteq(timestamp)) : where.not(finished_at: nil) }
|
13
23
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
24
|
+
def self.perform_with_advisory_lock(destroy_after: !GoodJob.preserve_job_records)
|
25
|
+
good_job = nil
|
26
|
+
result = nil
|
27
|
+
error = nil
|
28
|
+
|
29
|
+
unfinished.only_scheduled.limit(1).with_advisory_lock do |good_jobs|
|
30
|
+
good_job = good_jobs.first
|
31
|
+
break unless good_job
|
18
32
|
|
19
|
-
|
20
|
-
|
33
|
+
result, error = good_job.perform(destroy_after: destroy_after)
|
34
|
+
end
|
21
35
|
|
22
|
-
|
23
|
-
|
24
|
-
break unless good_job
|
36
|
+
[good_job, result, error] if good_job
|
37
|
+
end
|
25
38
|
|
26
|
-
|
27
|
-
|
39
|
+
def self.perform_with_advisory_lock_and_preserve_job_records
|
40
|
+
perform_with_advisory_lock(destroy_after: false)
|
41
|
+
end
|
28
42
|
|
29
|
-
|
30
|
-
|
43
|
+
def self.perform_with_advisory_lock_and_destroy_job_records
|
44
|
+
perform_with_advisory_lock(destroy_after: true)
|
31
45
|
end
|
32
46
|
|
33
47
|
def self.enqueue(active_job, scheduled_at: nil, create_with_advisory_lock: false)
|
@@ -50,16 +64,43 @@ module GoodJob
|
|
50
64
|
good_job
|
51
65
|
end
|
52
66
|
|
53
|
-
def perform
|
67
|
+
def perform(destroy_after: true)
|
68
|
+
raise PreviouslyPerformedError, 'Cannot perform a job that has already been performed' if finished_at
|
69
|
+
|
70
|
+
result = nil
|
71
|
+
error = nil
|
72
|
+
|
54
73
|
ActiveSupport::Notifications.instrument("before_perform_job.good_job", { good_job: self })
|
74
|
+
self.performed_at = Time.current
|
75
|
+
save! unless destroy_after
|
76
|
+
|
55
77
|
ActiveSupport::Notifications.instrument("perform_job.good_job", { good_job: self }) do
|
56
78
|
params = serialized_params.merge(
|
57
79
|
"provider_job_id" => id
|
58
80
|
)
|
59
|
-
|
81
|
+
begin
|
82
|
+
result = ActiveJob::Base.execute(params)
|
83
|
+
rescue StandardError => e
|
84
|
+
error = e
|
85
|
+
end
|
86
|
+
end
|
60
87
|
|
88
|
+
if error.nil? && result.is_a?(Exception)
|
89
|
+
error = result
|
90
|
+
result = nil
|
91
|
+
end
|
92
|
+
|
93
|
+
error_message = "#{error.class}: #{error.message}" if error
|
94
|
+
self.error = error_message
|
95
|
+
self.finished_at = Time.current
|
96
|
+
|
97
|
+
if destroy_after
|
61
98
|
destroy!
|
99
|
+
else
|
100
|
+
save!
|
62
101
|
end
|
102
|
+
|
103
|
+
[result, error]
|
63
104
|
end
|
64
105
|
end
|
65
106
|
end
|
data/lib/good_job/scheduler.rb
CHANGED
@@ -15,19 +15,18 @@ module GoodJob
|
|
15
15
|
min_threads: 0,
|
16
16
|
max_threads: Concurrent.processor_count,
|
17
17
|
auto_terminate: true,
|
18
|
-
idletime:
|
19
|
-
max_queue:
|
20
|
-
fallback_policy: :
|
18
|
+
idletime: 60,
|
19
|
+
max_queue: -1,
|
20
|
+
fallback_policy: :discard,
|
21
21
|
}.freeze
|
22
22
|
|
23
23
|
def initialize(performer, timer_options: {}, pool_options: {})
|
24
24
|
raise ArgumentError, "Performer argument must implement #next" unless performer.respond_to?(:next)
|
25
25
|
|
26
26
|
@performer = performer
|
27
|
-
@pool =
|
27
|
+
@pool = ThreadPoolExecutor.new(DEFAULT_POOL_OPTIONS.merge(pool_options))
|
28
28
|
@timer = Concurrent::TimerTask.new(DEFAULT_TIMER_OPTIONS.merge(timer_options)) do
|
29
|
-
|
30
|
-
create_thread if idle_threads.positive?
|
29
|
+
create_thread
|
31
30
|
end
|
32
31
|
@timer.add_observer(self, :timer_observer)
|
33
32
|
@timer.execute
|
@@ -58,22 +57,36 @@ module GoodJob
|
|
58
57
|
end
|
59
58
|
|
60
59
|
def create_thread
|
60
|
+
return false unless @pool.ready_worker_count.positive?
|
61
|
+
|
61
62
|
future = Concurrent::Future.new(args: [@performer], executor: @pool) do |performer|
|
62
|
-
|
63
|
-
Rails.application.executor.wrap {
|
64
|
-
|
63
|
+
output = nil
|
64
|
+
Rails.application.executor.wrap { output = performer.next }
|
65
|
+
output
|
65
66
|
end
|
66
67
|
future.add_observer(self, :task_observer)
|
67
68
|
future.execute
|
68
69
|
end
|
69
70
|
|
70
|
-
def timer_observer(time, executed_task,
|
71
|
-
ActiveSupport::Notifications.instrument("finished_timer_task.good_job", { result: executed_task, error:
|
71
|
+
def timer_observer(time, executed_task, thread_error)
|
72
|
+
ActiveSupport::Notifications.instrument("finished_timer_task.good_job", { result: executed_task, error: thread_error, time: time })
|
73
|
+
end
|
74
|
+
|
75
|
+
def task_observer(time, output, thread_error)
|
76
|
+
ActiveSupport::Notifications.instrument("finished_job_task.good_job", { result: output, error: thread_error, time: time })
|
77
|
+
create_thread if output
|
72
78
|
end
|
73
79
|
|
74
|
-
|
75
|
-
|
76
|
-
|
80
|
+
class ThreadPoolExecutor < Concurrent::ThreadPoolExecutor
|
81
|
+
# https://github.com/ruby-concurrency/concurrent-ruby/issues/684#issuecomment-427594437
|
82
|
+
def ready_worker_count
|
83
|
+
synchronize do
|
84
|
+
workers_still_to_be_created = @max_length - @pool.length
|
85
|
+
workers_created_but_waiting = @ready.length
|
86
|
+
|
87
|
+
workers_still_to_be_created + workers_created_but_waiting
|
88
|
+
end
|
89
|
+
end
|
77
90
|
end
|
78
91
|
end
|
79
92
|
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: 0.
|
4
|
+
version: 1.0.2
|
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-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: concurrent-ruby
|
@@ -236,24 +236,27 @@ files:
|
|
236
236
|
- README.md
|
237
237
|
- exe/good_job
|
238
238
|
- lib/active_job/queue_adapters/good_job_adapter.rb
|
239
|
+
- lib/generators/good_job/install_generator.rb
|
240
|
+
- lib/generators/good_job/templates/migration.rb.erb
|
239
241
|
- lib/good_job.rb
|
240
242
|
- lib/good_job/adapter.rb
|
241
243
|
- lib/good_job/cli.rb
|
242
244
|
- lib/good_job/job.rb
|
243
245
|
- lib/good_job/lockable.rb
|
244
246
|
- lib/good_job/logging.rb
|
247
|
+
- lib/good_job/performer.rb
|
245
248
|
- lib/good_job/pg_locks.rb
|
246
249
|
- lib/good_job/railtie.rb
|
247
250
|
- lib/good_job/scheduler.rb
|
248
251
|
- lib/good_job/version.rb
|
249
|
-
homepage: https://github.com/
|
252
|
+
homepage: https://github.com/bensheldon/good_job
|
250
253
|
licenses:
|
251
254
|
- MIT
|
252
255
|
metadata:
|
253
256
|
bug_tracker_uri: https://github.com/bensheldon/good_job/issues
|
254
257
|
changelog_uri: https://github.com/bensheldon/good_job/blob/master/CHANGELOG.md
|
255
258
|
documentation_uri: https://rdoc.info/github/bensheldon/good_job
|
256
|
-
homepage_uri: https://github.com/
|
259
|
+
homepage_uri: https://github.com/bensheldon/good_job
|
257
260
|
source_code_uri: https://github.com/bensheldon/good_job
|
258
261
|
post_install_message:
|
259
262
|
rdoc_options:
|