good_job 2.17.1 → 3.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (28) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +44 -1
  3. data/README.md +45 -26
  4. data/app/charts/good_job/scheduled_by_queue_chart.rb +1 -1
  5. data/app/controllers/good_job/jobs_controller.rb +11 -11
  6. data/app/controllers/good_job/processes_controller.rb +1 -1
  7. data/app/filters/good_job/jobs_filter.rb +2 -2
  8. data/app/views/good_job/processes/index.html.erb +1 -9
  9. data/app/views/layouts/good_job/application.html.erb +1 -1
  10. data/lib/generators/good_job/templates/update/migrations/01_create_good_jobs.rb.erb +9 -0
  11. data/lib/good_job/adapter.rb +6 -49
  12. data/lib/good_job/configuration.rb +4 -4
  13. data/lib/good_job/current_thread.rb +2 -2
  14. data/lib/good_job/notifier/process_registration.rb +0 -4
  15. data/lib/good_job/version.rb +1 -1
  16. data/lib/good_job.rb +7 -9
  17. data/lib/models/good_job/active_job_job.rb +6 -219
  18. data/lib/{good_job → models/good_job}/cron_entry.rb +3 -3
  19. data/lib/models/good_job/execution.rb +3 -11
  20. data/lib/models/good_job/job.rb +224 -0
  21. data/lib/{good_job → models/good_job}/lockable.rb +0 -0
  22. data/lib/models/good_job/process.rb +0 -9
  23. metadata +23 -27
  24. data/lib/generators/good_job/templates/update/migrations/02_add_cron_at_to_good_jobs.rb.erb +0 -14
  25. data/lib/generators/good_job/templates/update/migrations/03_add_cron_key_cron_at_index_to_good_jobs.rb.erb +0 -20
  26. data/lib/generators/good_job/templates/update/migrations/04_create_good_job_processes.rb.erb +0 -17
  27. data/lib/generators/good_job/templates/update/migrations/04_index_good_job_jobs_on_finished_at.rb.erb +0 -25
  28. data/lib/good_job/job.rb +0 -11
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 869350074426db7d14fdf229402edf5f86be6eccb0403c160f464e36844586dd
4
- data.tar.gz: 972188f8afb342c260b3c5417988ece4a0d2a42dfcaf42da18b72a8a472f24a4
3
+ metadata.gz: 381f27d5c5f8fe4be355f3b2ea1e1f0bcd76f545d7378183b4faca9d6770a6cd
4
+ data.tar.gz: 20b315936f49810e9aa70e0bc8c2a37c140436212f2e84d15e05d275c93715ee
5
5
  SHA512:
6
- metadata.gz: e25f2531c4e6310304e3152a9e93291f0daa158ae78c2937a59d0a680abe705ba063b510cc1680cf1c856f45112789365fed8ddf9d15cf46eabb62afd5c9770d
7
- data.tar.gz: d35c3de5c5bdb857af39e17376500792e017ba66dea78ab0da21c37635cf37ea1af1af36af3d6dd0bd19328d2a8fea0ff01765d841fce9c3b5ed1b9b8090a74f
6
+ metadata.gz: f0f107ba18b85211856391873650309997a63e16d2ddc34e55bdbdb3f8563e595f2e3176cfaa1e13f65eaca70e75df0ff950562740d51c1a82bc885dfd3421ea
7
+ data.tar.gz: cc47bc865ca1264238b5253f9ab06c8ebdc840e5adaf3220366f622626f8fac872c5fec5cd3b939acfd60137af6d984a0b2a61aad19ccd3ea277708f3c291414
data/CHANGELOG.md CHANGED
@@ -1,5 +1,49 @@
1
1
  # Changelog
2
2
 
3
+ ## [v3.0.1](https://github.com/bensheldon/good_job/tree/v3.0.1) (2022-07-02)
4
+
5
+ [Full Changelog](https://github.com/bensheldon/good_job/compare/v3.0.0...v3.0.1)
6
+
7
+ **Closed issues:**
8
+
9
+ - ERROR: relation "good\_jobs" does not exist at character 454 [\#308](https://github.com/bensheldon/good_job/issues/308)
10
+
11
+ **Merged pull requests:**
12
+
13
+ - Fix `GoodJob.cleanup_preserved_jobs` to use `delete_all` instead of `destroy_all` [\#652](https://github.com/bensheldon/good_job/pull/652) ([bensheldon](https://github.com/bensheldon))
14
+ - Create codeql-analysis.yml [\#648](https://github.com/bensheldon/good_job/pull/648) ([bensheldon](https://github.com/bensheldon))
15
+
16
+ ## [v3.0.0](https://github.com/bensheldon/good_job/tree/v3.0.0) (2022-06-26)
17
+
18
+ [Full Changelog](https://github.com/bensheldon/good_job/compare/v2.99.0...v3.0.0)
19
+
20
+ **Implemented enhancements:**
21
+
22
+ - By default, preserve job records and automatically them clean up [\#545](https://github.com/bensheldon/good_job/pull/545) ([bensheldon](https://github.com/bensheldon))
23
+
24
+ **Merged pull requests:**
25
+
26
+ - Update tests to reflect default of `GoodJob.preserve_job_records = true`; update appraisal Gemfiles too [\#643](https://github.com/bensheldon/good_job/pull/643) ([bensheldon](https://github.com/bensheldon))
27
+ - Remove database migration shims and old migrations [\#642](https://github.com/bensheldon/good_job/pull/642) ([bensheldon](https://github.com/bensheldon))
28
+ - Remove support for EOL Rails 5.2 [\#637](https://github.com/bensheldon/good_job/pull/637) ([bensheldon](https://github.com/bensheldon))
29
+ - Remove/rename deprecated behavior and constants for GoodJob v3 [\#633](https://github.com/bensheldon/good_job/pull/633) ([bensheldon](https://github.com/bensheldon))
30
+
31
+ ## [v2.99.0](https://github.com/bensheldon/good_job/tree/v2.99.0) (2022-06-26)
32
+
33
+ [Full Changelog](https://github.com/bensheldon/good_job/compare/v2.17.1...v2.99.0)
34
+
35
+ **Closed issues:**
36
+
37
+ - How to accomplish user controlled recurring jobs? [\#640](https://github.com/bensheldon/good_job/issues/640)
38
+ - "uninitialized constant GoodJob::Execution" in development env [\#634](https://github.com/bensheldon/good_job/issues/634)
39
+
40
+ **Merged pull requests:**
41
+
42
+ - Create upgrade instructions for v2.99 -\> v3.0.0 [\#641](https://github.com/bensheldon/good_job/pull/641) ([bensheldon](https://github.com/bensheldon))
43
+ - Update development dependencies; delete Gemfile.lock in CI to avoid Ruby version dependency mismatches [\#639](https://github.com/bensheldon/good_job/pull/639) ([bensheldon](https://github.com/bensheldon))
44
+ - Put more model files in `lib/models` and align specs too [\#638](https://github.com/bensheldon/good_job/pull/638) ([bensheldon](https://github.com/bensheldon))
45
+ - Generate sha256 checksums on gem release too [\#636](https://github.com/bensheldon/good_job/pull/636) ([bensheldon](https://github.com/bensheldon))
46
+
3
47
  ## [v2.17.1](https://github.com/bensheldon/good_job/tree/v2.17.1) (2022-06-24)
4
48
 
5
49
  [Full Changelog](https://github.com/bensheldon/good_job/compare/v2.17.0...v2.17.1)
@@ -980,7 +1024,6 @@
980
1024
 
981
1025
  **Closed issues:**
982
1026
 
983
- - ERROR: relation "good\_jobs" does not exist at character 454 [\#308](https://github.com/bensheldon/good_job/issues/308)
984
1027
  - Add Frozen String Literal to all files [\#298](https://github.com/bensheldon/good_job/issues/298)
985
1028
  - Support for good\_job without Rails? [\#295](https://github.com/bensheldon/good_job/issues/295)
986
1029
 
data/README.md CHANGED
@@ -46,6 +46,7 @@ For more of the story of GoodJob, read the [introductory blog post](https://isla
46
46
  - [Cron-style repeating/recurring jobs](#cron-style-repeatingrecurring-jobs)
47
47
  - [Updating](#updating)
48
48
  - [Upgrading minor versions](#upgrading-minor-versions)
49
+ - [Upgrading v2 to v3](#upgrading-v2-to-v3)
49
50
  - [Upgrading v1 to v2](#upgrading-v1-to-v2)
50
51
  - [Go deeper](#go-deeper)
51
52
  - [Exceptions, retries, and reliability](#exceptions-retries-and-reliability)
@@ -143,9 +144,9 @@ For more of the story of GoodJob, read the [introductory blog post](https://isla
143
144
 
144
145
  ## Compatibility
145
146
 
146
- - **Ruby on Rails:** 5.2+
147
- - **Ruby:** MRI 2.5+. JRuby 9.2.13+
148
- - **Postgres:** 9.6+
147
+ - **Ruby on Rails:** 6.0+
148
+ - **Ruby:** Ruby 2.5+. JRuby 9.2.13+
149
+ - **Postgres:** 10.0+
149
150
 
150
151
  ## Configuration
151
152
 
@@ -279,7 +280,7 @@ Available configuration options are:
279
280
  - `cleanup_interval_seconds` (integer) Number of seconds a Scheduler will wait before cleaning up preserved jobs. Defaults to `nil`. Can also be set with the environment variable `GOOD_JOB_CLEANUP_INTERVAL_SECONDS`.
280
281
  - `inline_execution_respects_schedule` (boolean) Opt-in to future behavior of inline execution respecting scheduled jobs. Defaults to `false`.
281
282
  - `logger` ([Rails Logger](https://api.rubyonrails.org/classes/ActiveSupport/Logger.html)) lets you set a custom logger for GoodJob. It should be an instance of a Rails `Logger` (Default: `Rails.logger`).
282
- - `preserve_job_records` (boolean) keeps job records in your database even after jobs are completed. (Default: `false`)
283
+ - `preserve_job_records` (boolean) keeps job records in your database even after jobs are completed. (Default: `true`)
283
284
  - `retry_on_unhandled_error` (boolean) causes jobs to be re-queued and retried if they raise an instance of `StandardError`. Be advised this may lead to jobs being repeated infinitely ([see below for more on retries](#retries)). Instances of `Exception`, like SIGINT, will *always* be retried, regardless of this attribute’s value. (Default: `true`)
284
285
  - `on_thread_error` (proc, lambda, or callable) will be called when an Exception. It can be useful for logging errors to bug tracking services, like Sentry or Airbrake. Example:
285
286
 
@@ -310,8 +311,8 @@ Good Job’s general behavior can also be configured via attributes directly on
310
311
 
311
312
  - **`GoodJob.active_record_parent_class`** (string) The ActiveRecord parent class inherited by GoodJob's ActiveRecord model `GoodJob::Job` (defaults to `"ActiveRecord::Base"`). Configure this when using [multiple databases with ActiveRecord](https://guides.rubyonrails.org/active_record_multiple_databases.html) or when other custom configuration is necessary for the ActiveRecord model to connect to the Postgres database. _The value must be a String to avoid premature initialization of ActiveRecord._
312
313
  - **`GoodJob.logger`** ([Rails Logger](https://api.rubyonrails.org/classes/ActiveSupport/Logger.html)) lets you set a custom logger for GoodJob. It should be an instance of a Rails `Logger`.
313
- - **`GoodJob.preserve_job_records`** (boolean) keeps job records in your database even after jobs are completed. (Default: `false`)
314
- - **`GoodJob.retry_on_unhandled_error`** (boolean) causes jobs to be re-queued and retried if they raise an instance of `StandardError`. Be advised this may lead to jobs being repeated infinitely ([see below for more on retries](#retries)). Instances of `Exception`, like SIGINT, will *always* be retried, regardless of this attribute’s value. (Default: `true`)
314
+ - **`GoodJob.preserve_job_records`** (boolean) keeps job records in your database even after jobs are completed. (Default: `true`)
315
+ - **`GoodJob.retry_on_unhandled_error`** (boolean) causes jobs to be re-queued and retried if they raise an instance of `StandardError`. Be advised this may lead to jobs being repeated infinitely ([see below for more on retries](#retries)). Instances of `Exception`, like SIGINT, will *always* be retried, regardless of this attribute’s value. (Default: `false`)
315
316
  - **`GoodJob.on_thread_error`** (proc, lambda, or callable) will be called when an Exception. It can be useful for logging errors to bug tracking services, like Sentry or Airbrake.
316
317
 
317
318
  You’ll generally want to configure these in `config/initializers/good_job.rb`, like so:
@@ -394,8 +395,6 @@ The Dashboard can be set to automatically refresh by checking "Live Poll" in the
394
395
 
395
396
  GoodJob can extend ActiveJob to provide limits on concurrently running jobs, either at time of _enqueue_ or at _perform_. Limiting concurrency can help prevent duplicate, double or unecessary jobs from being enqueued, or race conditions when performing, for example when interacting with 3rd-party APIs.
396
397
 
397
- **Note:** Limiting concurrency at _enqueue_ requires Rails 6.0+ because Rails 5.2 cannot halt ActiveJob callbacks.
398
-
399
398
  ```ruby
400
399
  class MyJob < ApplicationJob
401
400
  include GoodJob::ActiveJobExtensions::Concurrency
@@ -509,9 +508,25 @@ To perform upgrades to the GoodJob database tables:
509
508
  1. Commit the migration files and resulting `db/schema.rb` changes.
510
509
  1. Deploy the code, run the migrations against the production database, and restart server/worker processes.
511
510
 
511
+ #### Upgrading v2 to v3
512
+
513
+ GoodJob v3 is operationally identical to v2; upgrading to GoodJob v3 should be simple. If you are already using `>= v2.9+` no other changes are necessary.
514
+
515
+ 1. Upgrade to `v2.99.x`, following the minor version upgrade process, running any remaining database migrations (`rails g good_job:update`) and addressing deprecation warnings.
516
+ 1. Upgrade from `v2.99.x` to `v3.x`
517
+
518
+ Notable changes:
519
+
520
+ - Defaults to preserve job records, and automatically delete them after 14 days.
521
+ - Defaults to discarding failed jobs, instead of immediately retrying them.
522
+ - `:inline` execution mode respects job schedules. Tests can invoke `GoodJob.perform_inline` to execute jobs.
523
+ - `GoodJob::Adapter` can no longer can be initialized with custom execution options (`queues:`, `max_threads:`, `poll_interval:`).
524
+ - Renames `GoodJob::ActiveJobJob` to `GoodJob::Job`.
525
+ - Removes support for Rails 5.2.
526
+
512
527
  #### Upgrading v1 to v2
513
528
 
514
- GoodJob v2 introduces a new Advisory Lock key format that is different than the v1 advisory lock key format; it's therefore necessary to perform a simple, but staged production upgrade. If you are already using `>= v1.12+` no other changes are necessary.
529
+ GoodJob v2 introduces a new Advisory Lock key format that is operationally different than the v1 advisory lock key format; it's therefore necessary to perform a simple, but staged production upgrade. If you are already using `>= v1.12+` no other changes are necessary.
515
530
 
516
531
  1. Upgrade your production environment to `v1.99.x` following the minor version upgrade process, including database migrations. `v1.99` is a transitional release that is safely compatible with both `v1.x` and `v2.0.0` because it uses both `v1`- and `v2`-formatted advisory locks.
517
532
  1. Address any deprecation warnings generated by `v1.99`.
@@ -547,9 +562,9 @@ GoodJob.on_thread_error = -> (exception) { Raven.capture_exception(exception) }
547
562
 
548
563
  #### Retries
549
564
 
550
- By default, GoodJob will automatically and immediately retry a job when an exception is raised to GoodJob.
565
+ By default, GoodJob relies on ActiveJob's retry functionality.
551
566
 
552
- However, ActiveJob can be configured to retry an infinite number of times, with an exponential backoff. Using ActiveJob's `retry_on` prevents exceptions from reaching GoodJob:
567
+ ActiveJob can be configured to retry an infinite number of times, with an exponential backoff. Using ActiveJob's `retry_on` prevents exceptions from reaching GoodJob:
553
568
 
554
569
  ```ruby
555
570
  class ApplicationJob < ActiveJob::Base
@@ -558,14 +573,7 @@ class ApplicationJob < ActiveJob::Base
558
573
  end
559
574
  ```
560
575
 
561
- When using `retry_on` with _a limited number of retries_, the final exception will not be rescued and will raise to GoodJob. GoodJob can be configured to discard un-handled exceptions instead of retrying them. Be aware that if NOT setting `retry_on_unhandled_error` to `false` good_job will by default retry the failing job and may do this infinitely without pause thereby at least causing high load. In most cases `retry_on_unhandled_error` should be set as following:
562
-
563
- ```ruby
564
- # config/initializers/good_job.rb
565
- GoodJob.retry_on_unhandled_error = false
566
- ```
567
-
568
- Alternatively, pass a block to `retry_on` to handle the final exception instead of raising it to GoodJob:
576
+ When using `retry_on` with _a limited number of retries_, the final exception will not be rescued and will raise to GoodJob's error handler. To avoid this, pass a block to `retry_on` to handle the final exception instead of raising it to GoodJob:
569
577
 
570
578
  ```ruby
571
579
  class ApplicationJob < ActiveJob::Base
@@ -596,9 +604,11 @@ class ApplicationJob < ActiveJob::Base
596
604
  end
597
605
  ```
598
606
 
607
+ By default, jobs will not be retried unless `retry_on` is configured. This can be overridden by setting `GoodJob.retry_on_unhandled_error` to `true`; GoodJob will then retry the failing job immediately and infinitely, potentially causing high load.
608
+
599
609
  #### ActionMailer retries
600
610
 
601
- Any configuration in `ApplicationJob` will have to be duplicated on `ActionMailer::MailDeliveryJob` (`ActionMailer::DeliveryJob` in Rails 5.2 or earlier) because ActionMailer uses a custom class, `ActionMailer::MailDeliveryJob`, which inherits from `ActiveJob::Base`, rather than your applications `ApplicationJob`.
611
+ Any configuration in `ApplicationJob` will have to be duplicated on `ActionMailer::MailDeliveryJob` because ActionMailer uses that custom class which inherits from `ActiveJob::Base`, rather than your application's `ApplicationJob`.
602
612
 
603
613
  You can use an initializer to configure `ActionMailer::MailDeliveryJob`, for example:
604
614
 
@@ -852,22 +862,31 @@ If your application is already using an ActiveJob backend, you will need to inst
852
862
 
853
863
  GoodJob is fully instrumented with [`ActiveSupport::Notifications`](https://edgeguides.rubyonrails.org/active_support_instrumentation.html#introduction-to-instrumentation).
854
864
 
855
- By default, GoodJob will destroy 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`).
865
+ By default, GoodJob will preserve job records for 14 days 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`).
856
866
 
857
- To preserve job records for later inspection, set an initializer:
867
+ To not preserve job records for later inspection, set an initializer:
858
868
 
859
869
  ```ruby
860
870
  # config/initializers/good_job.rb
861
- GoodJob.preserve_job_records = true
871
+ GoodJob.preserve_job_records = false # defaults to true, or `false` or `:on_unhandled_error`
872
+ ```
873
+
874
+ GoodJob will automatically delete these job records after 14 days. The retention period, as well as the frequency GoodJob checks for deletable records can be configured:
875
+
876
+ ```ruby
877
+
878
+ config.cleanup_preserved_jobs_before_seconds_ago = 14.days.to_i
879
+ config.cleanup_interval_jobs = 1_000 # Number of executed jobs between deletion sweeps.
880
+ config.cleanup_interval_seconds = 10.minutes.to_i # Number of seconds between deletion sweeps.
862
881
  ```
863
882
 
864
- It is also necessary to destroy these preserved jobs from the database after a certain time period:
883
+ It is also possible to manually trigger a cleanup:
865
884
 
866
885
  - For example, in a Rake task:
867
886
 
868
887
  ```ruby
869
- GoodJob.cleanup_preserved_jobs # Will keep 1 day of job records by default.
870
- GoodJob.cleanup_preserved_jobs(older_than: 7.days) # It also takes custom arguments.
888
+ GoodJob.cleanup_preserved_jobs # Will use default retention period
889
+ GoodJob.cleanup_preserved_jobs(older_than: 7.days) # custom retention period
871
890
  ```
872
891
 
873
892
  - For example, using the `good_job` command-line utility:
@@ -9,7 +9,7 @@ module GoodJob
9
9
  def data
10
10
  end_time = Time.current
11
11
  start_time = end_time - 1.day
12
- table_name = GoodJob::ActiveJobJob.table_name
12
+ table_name = GoodJob::Job.table_name
13
13
 
14
14
  count_query = Arel.sql(GoodJob::Execution.pg_or_jdbc_query(<<~SQL.squish))
15
15
  SELECT *
@@ -10,8 +10,8 @@ module GoodJob
10
10
  destroy: "destroyed",
11
11
  }.freeze
12
12
 
13
- rescue_from GoodJob::ActiveJobJob::AdapterNotGoodJobError,
14
- GoodJob::ActiveJobJob::ActionForStateMismatchError,
13
+ rescue_from GoodJob::Job::AdapterNotGoodJobError,
14
+ GoodJob::Job::ActionForStateMismatchError,
15
15
  with: :redirect_on_error
16
16
 
17
17
  def index
@@ -26,7 +26,7 @@ module GoodJob
26
26
  JobsFilter.new(params).filtered_query
27
27
  else
28
28
  job_ids = params.fetch(:job_ids, [])
29
- ActiveJobJob.where(active_job_id: job_ids)
29
+ Job.where(active_job_id: job_ids)
30
30
  end
31
31
 
32
32
  processed_jobs = jobs.map do |job|
@@ -42,7 +42,7 @@ module GoodJob
42
42
  end
43
43
 
44
44
  job
45
- rescue GoodJob::ActiveJobJob::ActionForStateMismatchError
45
+ rescue GoodJob::Job::ActionForStateMismatchError
46
46
  nil
47
47
  end.compact
48
48
 
@@ -56,29 +56,29 @@ module GoodJob
56
56
  end
57
57
 
58
58
  def show
59
- @job = ActiveJobJob.find(params[:id])
59
+ @job = Job.find(params[:id])
60
60
  end
61
61
 
62
62
  def discard
63
- @job = ActiveJobJob.find(params[:id])
63
+ @job = Job.find(params[:id])
64
64
  @job.discard_job(DISCARD_MESSAGE)
65
65
  redirect_back(fallback_location: jobs_path, notice: "Job has been discarded")
66
66
  end
67
67
 
68
68
  def reschedule
69
- @job = ActiveJobJob.find(params[:id])
69
+ @job = Job.find(params[:id])
70
70
  @job.reschedule_job
71
71
  redirect_back(fallback_location: jobs_path, notice: "Job has been rescheduled")
72
72
  end
73
73
 
74
74
  def retry
75
- @job = ActiveJobJob.find(params[:id])
75
+ @job = Job.find(params[:id])
76
76
  @job.retry_job
77
77
  redirect_back(fallback_location: jobs_path, notice: "Job has been retried")
78
78
  end
79
79
 
80
80
  def destroy
81
- @job = ActiveJobJob.find(params[:id])
81
+ @job = Job.find(params[:id])
82
82
  @job.destroy_job
83
83
  redirect_back(fallback_location: jobs_path, notice: "Job has been destroyed")
84
84
  end
@@ -87,9 +87,9 @@ module GoodJob
87
87
 
88
88
  def redirect_on_error(exception)
89
89
  alert = case exception
90
- when GoodJob::ActiveJobJob::AdapterNotGoodJobError
90
+ when GoodJob::Job::AdapterNotGoodJobError
91
91
  "ActiveJob Queue Adapter must be GoodJob."
92
- when GoodJob::ActiveJobJob::ActionForStateMismatchError
92
+ when GoodJob::Job::ActionForStateMismatchError
93
93
  "Job is not in an appropriate state for this action."
94
94
  else
95
95
  exception.to_s
@@ -2,7 +2,7 @@
2
2
  module GoodJob
3
3
  class ProcessesController < GoodJob::ApplicationController
4
4
  def index
5
- @processes = GoodJob::Process.active.order(created_at: :desc) if GoodJob::Process.migrated?
5
+ @processes = GoodJob::Process.active.order(created_at: :desc)
6
6
  end
7
7
  end
8
8
  end
@@ -31,7 +31,7 @@ module GoodJob
31
31
  when 'scheduled'
32
32
  query = query.scheduled
33
33
  when 'running'
34
- query = query.running.select("#{GoodJob::ActiveJobJob.table_name}.*", 'pg_locks.locktype')
34
+ query = query.running.select("#{GoodJob::Job.table_name}.*", 'pg_locks.locktype')
35
35
  when 'queued'
36
36
  query = query.queued
37
37
  end
@@ -47,7 +47,7 @@ module GoodJob
47
47
  private
48
48
 
49
49
  def default_base_query
50
- GoodJob::ActiveJobJob.all
50
+ GoodJob::Job.all
51
51
  end
52
52
  end
53
53
  end
@@ -3,15 +3,7 @@
3
3
  </div>
4
4
 
5
5
  <div data-live-poll-region="processes">
6
- <% if !GoodJob::Process.migrated? %>
7
- <div class="card my-3">
8
- <div class="card-body">
9
- <p class="card-text">
10
- <em>Feature unavailable because of pending database migration.</em>
11
- </p>
12
- </div>
13
- </div>
14
- <% elsif @processes.present? %>
6
+ <% if @processes.present? %>
15
7
  <div class="card my-3">
16
8
  <div class="table-responsive">
17
9
  <table class="table card-table table-bordered table-hover table-sm mb-0">
@@ -16,7 +16,7 @@
16
16
  <%= tag.script "", src: rails_ujs_path(format: :js, v: GoodJob::VERSION, locale: nil), nonce: content_security_policy_nonce %>
17
17
 
18
18
  <%= tag.script "", src: es_module_shims_path(format: :js, v: GoodJob::VERSION, locale: nil), async: true, nonce: content_security_policy_nonce %>
19
- <% importmaps = { imports: GoodJob::AssetsController.js_modules.keys.each_with_object({}) { |module_name, imports| imports[module_name] = modules_path(module_name, format: :js, locale: nil, v: GoodJob::VERSION) } } %>
19
+ <% importmaps = { imports: GoodJob::AssetsController.js_modules.keys.index_with { |module_name| modules_path(module_name, format: :js, locale: nil, v: GoodJob::VERSION) } } %>
20
20
  <%= tag.script importmaps.to_json.html_safe, type: "importmap", nonce: content_security_policy_nonce %>
21
21
  <%= tag.script "", src: scripts_path(format: :js, v: GoodJob::VERSION, locale: nil), type: "module", nonce: content_security_policy_nonce %>
22
22
  </head>
@@ -18,6 +18,12 @@ class CreateGoodJobs < ActiveRecord::Migration<%= migration_version %>
18
18
  t.text :concurrency_key
19
19
  t.text :cron_key
20
20
  t.uuid :retried_good_job_id
21
+ t.timestamp :cron_at
22
+ end
23
+
24
+ create_table :good_job_processes, id: :uuid do |t|
25
+ t.timestamps
26
+ t.jsonb :state
21
27
  end
22
28
 
23
29
  add_index :good_jobs, :scheduled_at, where: "(finished_at IS NULL)", name: "index_good_jobs_on_scheduled_at"
@@ -25,5 +31,8 @@ class CreateGoodJobs < ActiveRecord::Migration<%= migration_version %>
25
31
  add_index :good_jobs, [:active_job_id, :created_at], name: :index_good_jobs_on_active_job_id_and_created_at
26
32
  add_index :good_jobs, :concurrency_key, where: "(finished_at IS NULL)", name: :index_good_jobs_on_concurrency_key_when_unfinished
27
33
  add_index :good_jobs, [:cron_key, :created_at], name: :index_good_jobs_on_cron_key_and_created_at
34
+ add_index :good_jobs, [:cron_key, :cron_at], name: :index_good_jobs_on_cron_key_and_cron_at, unique: true
35
+ add_index :good_jobs, [:active_job_id], name: :index_good_jobs_on_active_job_id
36
+ add_index :good_jobs, [:finished_at], where: "retried_good_job_id IS NULL AND finished_at IS NOT NULL", name: :index_good_jobs_jobs_on_finished_at
28
37
  end
29
38
  end
@@ -20,32 +20,16 @@ module GoodJob
20
20
  #
21
21
  # The default value depends on the Rails environment:
22
22
  #
23
- # - +development+ and +test+: +:inline+
23
+ # - +development+: +:async:+
24
+ # -+test+: +:inline+
24
25
  # - +production+ and all other environments: +:external+
25
26
  #
26
- # @param max_threads [Integer, nil] sets the number of threads per scheduler to use when +execution_mode+ is set to +:async+. The +queues+ parameter can specify a number of threads for each group of queues which will override this value. You can also set this with the environment variable +GOOD_JOB_MAX_THREADS+. Defaults to +5+.
27
- # @param queues [String, nil] determines which queues to execute jobs from when +execution_mode+ is set to +:async+. See {file:README.md#optimize-queues-threads-and-processes} for more details on the format of this string. You can also set this with the environment variable +GOOD_JOB_QUEUES+. Defaults to +"*"+.
28
- # @param poll_interval [Integer, nil] sets the number of seconds between polls for jobs when +execution_mode+ is set to +:async+. You can also set this with the environment variable +GOOD_JOB_POLL_INTERVAL+. Defaults to +1+.
29
- # @param start_async_on_initialize [Boolean] whether to start the async scheduler when the adapter is initialized.
30
- def initialize(execution_mode: nil, queues: nil, max_threads: nil, poll_interval: nil, start_async_on_initialize: nil)
31
- if queues || max_threads || poll_interval || start_async_on_initialize
32
- ActiveSupport::Deprecation.warn(
33
- "GoodJob::Adapter's execution-related arguments (queues, max_threads, poll_interval, start_async_on_initialize) have been deprecated and will be removed in GoodJob v3. These options should be configured through GoodJob global configuration instead."
34
- )
35
- end
36
-
37
- @configuration = GoodJob::Configuration.new(
38
- {
39
- execution_mode: execution_mode,
40
- queues: queues,
41
- max_threads: max_threads,
42
- poll_interval: poll_interval,
43
- }
44
- )
27
+ def initialize(execution_mode: nil)
28
+ @configuration = GoodJob::Configuration.new({ execution_mode: execution_mode })
45
29
  @configuration.validate!
46
30
  self.class.instances << self
47
31
 
48
- start_async if start_async_on_initialize || GoodJob.async_ready?
32
+ start_async if GoodJob.async_ready?
49
33
  end
50
34
 
51
35
  # Enqueues the ActiveJob job to be performed.
@@ -63,11 +47,7 @@ module GoodJob
63
47
  # @return [GoodJob::Execution]
64
48
  def enqueue_at(active_job, timestamp)
65
49
  scheduled_at = timestamp ? Time.zone.at(timestamp) : nil
66
-
67
- if execute_inline?
68
- future_scheduled = scheduled_at && scheduled_at > Time.current
69
- will_execute_inline = !future_scheduled || (future_scheduled && !@configuration.inline_execution_respects_schedule?)
70
- end
50
+ will_execute_inline = execute_inline? && (scheduled_at.nil? || scheduled_at <= Time.current)
71
51
 
72
52
  execution = GoodJob::Execution.enqueue(
73
53
  active_job,
@@ -76,29 +56,6 @@ module GoodJob
76
56
  )
77
57
 
78
58
  if will_execute_inline
79
- if future_scheduled && !@configuration.inline_execution_respects_schedule?
80
- ActiveSupport::Deprecation.warn(<<~DEPRECATION)
81
- In the next major release, GoodJob will not *inline* execute
82
- future-scheduled jobs.
83
-
84
- To opt into this behavior immediately set:
85
- `config.good_job.inline_execution_respects_schedule = true`
86
-
87
- To perform jobs inline at any time, use `GoodJob.perform_inline`.
88
-
89
- For example, using time helpers within an integration test:
90
-
91
- ```
92
- MyJob.set(wait: 10.minutes).perform_later
93
- travel_to(15.minutes.from_now) { GoodJob.perform_inline }
94
- ```
95
-
96
- Note: Rails `travel`/`travel_to` time helpers do not have millisecond
97
- precision, so you must leave at least 1 second between the schedule
98
- and time traveling for the job to be executed.
99
- DEPRECATION
100
- end
101
-
102
59
  begin
103
60
  result = execution.perform
104
61
  ensure
@@ -15,13 +15,13 @@ module GoodJob
15
15
  # Default poll interval for async in development environment
16
16
  DEFAULT_DEVELOPMENT_ASYNC_POLL_INTERVAL = -1
17
17
  # Default number of threads to use per {Scheduler}
18
- DEFAULT_MAX_CACHE = 10000
18
+ DEFAULT_MAX_CACHE = 10_000
19
19
  # Default number of seconds to preserve jobs for {CLI#cleanup_preserved_jobs} and {GoodJob.cleanup_preserved_jobs}
20
- DEFAULT_CLEANUP_PRESERVED_JOBS_BEFORE_SECONDS_AGO = 24 * 60 * 60
20
+ DEFAULT_CLEANUP_PRESERVED_JOBS_BEFORE_SECONDS_AGO = 14.days.to_i
21
21
  # Default number of jobs to execute between preserved job cleanup runs
22
- DEFAULT_CLEANUP_INTERVAL_JOBS = nil
22
+ DEFAULT_CLEANUP_INTERVAL_JOBS = 1_000
23
23
  # Default number of seconds to wait between preserved job cleanup runs
24
- DEFAULT_CLEANUP_INTERVAL_SECONDS = nil
24
+ DEFAULT_CLEANUP_INTERVAL_SECONDS = 10.minutes.to_i
25
25
  # Default to always wait for jobs to finish for {Adapter#shutdown}
26
26
  DEFAULT_SHUTDOWN_TIMEOUT = -1
27
27
  # Default to not running cron
@@ -56,8 +56,8 @@ module GoodJob
56
56
  # Exports values to hash
57
57
  # @return [Hash]
58
58
  def self.to_h
59
- ACCESSORS.each_with_object({}) do |accessor, hash|
60
- hash[accessor] = send(accessor)
59
+ ACCESSORS.index_with do |accessor|
60
+ send(accessor)
61
61
  end
62
62
  end
63
63
 
@@ -14,8 +14,6 @@ module GoodJob # :nodoc:
14
14
  # Registers the current process.
15
15
  def register_process
16
16
  GoodJob::Process.with_connection(connection) do
17
- next unless Process.migrated?
18
-
19
17
  GoodJob::Process.cleanup
20
18
  @process = GoodJob::Process.register
21
19
  end
@@ -24,8 +22,6 @@ module GoodJob # :nodoc:
24
22
  # Deregisters the current process.
25
23
  def deregister_process
26
24
  GoodJob::Process.with_connection(connection) do
27
- next unless Process.migrated?
28
-
29
25
  @process&.deregister
30
26
  end
31
27
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
  module GoodJob
3
3
  # GoodJob gem version.
4
- VERSION = '2.17.1'
4
+ VERSION = '3.0.1'
5
5
  end
data/lib/good_job.rb CHANGED
@@ -43,23 +43,21 @@ module GoodJob
43
43
 
44
44
  # @!attribute [rw] preserve_job_records
45
45
  # @!scope class
46
- # Whether to preserve job records in the database after they have finished (default: +false+).
47
- # By default, GoodJob destroys job records after the job is completed successfully.
46
+ # Whether to preserve job records in the database after they have finished (default: +true+).
47
+ # By default, GoodJob deletes job records after the job is completed successfully.
48
48
  # If you want to preserve jobs for latter inspection, set this to +true+.
49
49
  # If you want to preserve only jobs that finished with error for latter inspection, set this to +:on_unhandled_error+.
50
- # If +true+, you will need to clean out jobs using the +good_job cleanup_preserved_jobs+ CLI command or
51
- # by using +Goodjob.cleanup_preserved_jobs+.
52
50
  # @return [Boolean, nil]
53
- mattr_accessor :preserve_job_records, default: false
51
+ mattr_accessor :preserve_job_records, default: true
54
52
 
55
53
  # @!attribute [rw] retry_on_unhandled_error
56
54
  # @!scope class
57
- # Whether to re-perform a job when a type of +StandardError+ is raised to GoodJob (default: +true+).
55
+ # Whether to re-perform a job when a type of +StandardError+ is raised to GoodJob (default: +false+).
58
56
  # If +true+, causes jobs to be re-queued and retried if they raise an instance of +StandardError+.
59
57
  # If +false+, jobs will be discarded or marked as finished if they raise an instance of +StandardError+.
60
58
  # Instances of +Exception+, like +SIGINT+, will *always* be retried, regardless of this attribute's value.
61
59
  # @return [Boolean, nil]
62
- mattr_accessor :retry_on_unhandled_error, default: true
60
+ mattr_accessor :retry_on_unhandled_error, default: false
63
61
 
64
62
  # @!attribute [rw] on_thread_error
65
63
  # @!scope class
@@ -143,11 +141,11 @@ module GoodJob
143
141
  include_discarded = configuration.cleanup_discarded_jobs?
144
142
 
145
143
  ActiveSupport::Notifications.instrument("cleanup_preserved_jobs.good_job", { older_than: older_than, timestamp: timestamp }) do |payload|
146
- old_jobs = GoodJob::ActiveJobJob.where('finished_at <= ?', timestamp)
144
+ old_jobs = GoodJob::Job.where('finished_at <= ?', timestamp)
147
145
  old_jobs = old_jobs.not_discarded unless include_discarded
148
146
  old_jobs_count = old_jobs.count
149
147
 
150
- GoodJob::Execution.where(job: old_jobs).destroy_all
148
+ GoodJob::Execution.where(job: old_jobs).delete_all
151
149
  payload[:destroyed_records_count] = old_jobs_count
152
150
  end
153
151
  end