good_job 3.4.7 → 3.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8994365182a8cc05445c3368e6dea0bb2ccedf2678f59bd5612280b8154c1ee3
4
- data.tar.gz: 3a4d3f05f8e3a862abadd24a6f6b68b1bc969740b9bf14dab5328b055c9e3835
3
+ metadata.gz: 7cc0961bf8aed9531b101c7d9a2be80693bd16dadf7239aa76b25adfea24f27c
4
+ data.tar.gz: 0740f33be940345ef16ebea8a8f188ebac56fe27af260f5510e7ed3d2ce98a96
5
5
  SHA512:
6
- metadata.gz: cb67c0a6c3979b29a59b74b33c1097b9c38b53f7e678e80368e9f28829fe31703fe9d4f2c2a710783e3f5e650467fc7c196433c49c1c55b0b3522c3d6d5a7645
7
- data.tar.gz: 6a114ae3a9509b2987b49ad65547ac0b12adb16de93127d0d72c9a4a86850f60680bed12468e7e94a5718ad5f364419b8b2daf609800d52f1f6ec9c6c1362340
6
+ metadata.gz: 0bdb4e1dab74099990750ea9239fe741432969d4aa412a8fdead0cbd4b43f5a7ae07732c78ff7ce82aedd534d5c6a27122be1c4b390f75982531ec0ed37ad9e8
7
+ data.tar.gz: 04b50734aab939660d38b28076c1ca7fe13f19894fe419cd09f9d099c1cdb2253c9ec0d8c90fdb54fe2bdeeff58646e3f366f3bcaf86638bb9dbd579194bb4c1
data/CHANGELOG.md CHANGED
@@ -1,5 +1,23 @@
1
1
  # Changelog
2
2
 
3
+ ## [v3.5.0](https://github.com/bensheldon/good_job/tree/v3.5.0) (2022-10-18)
4
+
5
+ [Full Changelog](https://github.com/bensheldon/good_job/compare/v3.4.8...v3.5.0)
6
+
7
+ **Merged pull requests:**
8
+
9
+ - Fix flaky test for `Scheduler#cleanup_interval_jobs` [\#723](https://github.com/bensheldon/good_job/pull/723) ([bensheldon](https://github.com/bensheldon))
10
+ - Pin development Puma version until Capybara is compatible [\#722](https://github.com/bensheldon/good_job/pull/722) ([bensheldon](https://github.com/bensheldon))
11
+ - Rename Job status of `finished` to `succeeded`; `finished` now means either `succeeded` or `discarded` [\#721](https://github.com/bensheldon/good_job/pull/721) ([bensheldon](https://github.com/bensheldon))
12
+
13
+ ## [v3.4.8](https://github.com/bensheldon/good_job/tree/v3.4.8) (2022-10-11)
14
+
15
+ [Full Changelog](https://github.com/bensheldon/good_job/compare/v3.4.7...v3.4.8)
16
+
17
+ **Merged pull requests:**
18
+
19
+ - When not preserving job records, ensure all prior executions are deleted after successful retry [\#719](https://github.com/bensheldon/good_job/pull/719) ([ylansegal](https://github.com/ylansegal))
20
+
3
21
  ## [v3.4.7](https://github.com/bensheldon/good_job/tree/v3.4.7) (2022-10-06)
4
22
 
5
23
  [Full Changelog](https://github.com/bensheldon/good_job/compare/v3.4.6...v3.4.7)
data/README.md CHANGED
@@ -363,7 +363,7 @@ GoodJob includes a Dashboard as a mountable `Rails::Engine`.
363
363
  end
364
364
  ```
365
365
 
366
- _To view finished (successful) and discarded (failed) jobs on the Dashboard, GoodJob must be configured to preserve job records. Preservation is enabled by default._
366
+ _To view finished jobs (succeeded and discarded) on the Dashboard, GoodJob must be configured to preserve job records. Preservation is enabled by default._
367
367
 
368
368
  **Troubleshooting the Dashboard:** Some applications are unable to autoload the Goodjob Engine. To work around this, explicitly require the Engine at the top of your `config/application.rb` file, immediately after Rails is required and before Bundler requires the Rails' groups.
369
369
 
@@ -8,7 +8,7 @@ module GoodJob
8
8
  'retried' => query.retried.count,
9
9
  'queued' => query.queued.count,
10
10
  'running' => query.running.count,
11
- 'finished' => query.finished.count,
11
+ 'succeeded' => query.succeeded.count,
12
12
  'discarded' => query.discarded.count,
13
13
  }
14
14
  end
@@ -25,8 +25,8 @@ module GoodJob
25
25
  case filter_params[:state]
26
26
  when 'discarded'
27
27
  query = query.discarded
28
- when 'finished'
29
- query = query.finished
28
+ when 'succeeded'
29
+ query = query.succeeded
30
30
  when 'retried'
31
31
  query = query.retried
32
32
  when 'scheduled'
@@ -24,7 +24,7 @@ module GoodJob
24
24
 
25
25
  STATUS_ICONS = {
26
26
  discarded: "exclamation",
27
- finished: "check",
27
+ succeeded: "check",
28
28
  queued: "dash_circle",
29
29
  retried: "arrow_clockwise",
30
30
  running: "play",
@@ -33,7 +33,7 @@ module GoodJob
33
33
 
34
34
  STATUS_COLOR = {
35
35
  discarded: "danger",
36
- finished: "success",
36
+ succeeded: "success",
37
37
  queued: "secondary",
38
38
  retried: "warning",
39
39
  running: "primary",
@@ -8,8 +8,8 @@ module GoodJob
8
8
  # - retried: The job previously errored on execution and will be re-executed in the future.
9
9
  # 2. The job is being executed
10
10
  # - running: the job is actively being executed by an execution thread
11
- # 3. The job will not execute
12
- # - finished: The job executed successfully
11
+ # 3. The job has finished
12
+ # - succeeded: The job executed successfully
13
13
  # - discarded: The job previously errored on execution and will not be re-executed in the future.
14
14
  #
15
15
  # @return [Symbol]
@@ -20,7 +20,7 @@ module GoodJob
20
20
  elsif error.present? && retried_good_job_id.nil?
21
21
  :discarded
22
22
  else
23
- :finished
23
+ :succeeded
24
24
  end
25
25
  elsif (scheduled_at || created_at) > DateTime.current
26
26
  if serialized_params.fetch('executions', 0) > 1
@@ -66,8 +66,9 @@ module GoodJob
66
66
  end
67
67
 
68
68
  belongs_to :job, class_name: 'GoodJob::Job', foreign_key: 'active_job_id', primary_key: 'active_job_id', optional: true, inverse_of: :executions
69
+ after_destroy -> { self.class.active_job_id(active_job_id).delete_all }, if: -> { @_destroy_job }
69
70
 
70
- # Get Jobs with given ActiveJob ID
71
+ # Get executions with given ActiveJob ID
71
72
  # @!method active_job_id
72
73
  # @!scope class
73
74
  # @param active_job_id [String]
@@ -75,7 +76,7 @@ module GoodJob
75
76
  # @return [ActiveRecord::Relation]
76
77
  scope :active_job_id, ->(active_job_id) { where(active_job_id: active_job_id) }
77
78
 
78
- # Get Jobs with given class name
79
+ # Get executions with given class name
79
80
  # @!method job_class
80
81
  # @!scope class
81
82
  # @param string [String]
@@ -83,32 +84,32 @@ module GoodJob
83
84
  # @return [ActiveRecord::Relation]
84
85
  scope :job_class, ->(job_class) { where("serialized_params->>'job_class' = ?", job_class) }
85
86
 
86
- # Get Jobs that have not yet been completed.
87
+ # Get executions that have not yet finished (succeeded or discarded).
87
88
  # @!method unfinished
88
89
  # @!scope class
89
90
  # @return [ActiveRecord::Relation]
90
91
  scope :unfinished, -> { where(finished_at: nil) }
91
92
 
92
- # Get Jobs that are not scheduled for a later time than now (i.e. jobs that
93
+ # Get executions that are not scheduled for a later time than now (i.e. jobs that
93
94
  # are not scheduled or scheduled for earlier than the current time).
94
95
  # @!method only_scheduled
95
96
  # @!scope class
96
97
  # @return [ActiveRecord::Relation]
97
98
  scope :only_scheduled, -> { where(arel_table['scheduled_at'].lteq(Time.current)).or(where(scheduled_at: nil)) }
98
99
 
99
- # Order jobs by priority (highest priority first).
100
+ # Order executions by priority (highest priority first).
100
101
  # @!method priority_ordered
101
102
  # @!scope class
102
103
  # @return [ActiveRecord::Relation]
103
104
  scope :priority_ordered, -> { order('priority DESC NULLS LAST') }
104
105
 
105
- # Order jobs by created_at, for first-in first-out
106
+ # Order executions by created_at, for first-in first-out
106
107
  # @!method creation_ordered
107
108
  # @!scope class
108
109
  # @return [ActiveRecord:Relation]
109
110
  scope :creation_ordered, -> { order('created_at ASC') }
110
111
 
111
- # Order jobs for de-queueing
112
+ # Order executions for de-queueing
112
113
  # @!method dequeueing_ordered
113
114
  # @!scope class
114
115
  # @param parsed_queues [Hash]
@@ -123,7 +124,7 @@ module GoodJob
123
124
  relation
124
125
  end)
125
126
 
126
- # Order jobs in order of queues in array param
127
+ # Order executions in order of queues in array param
127
128
  # @!method queue_ordered
128
129
  # @!scope class
129
130
  # @param queues [Array<string] ordered names of queues
@@ -298,11 +299,11 @@ module GoodJob
298
299
 
299
300
  if result.unhandled_error && GoodJob.retry_on_unhandled_error
300
301
  save!
301
- elsif GoodJob.preserve_job_records == true || (result.unhandled_error && GoodJob.preserve_job_records == :on_unhandled_error)
302
+ elsif GoodJob.preserve_job_records == true || result.retried? || (result.unhandled_error && GoodJob.preserve_job_records == :on_unhandled_error)
302
303
  self.finished_at = Time.current
303
304
  save!
304
305
  else
305
- destroy!
306
+ destroy_job
306
307
  end
307
308
 
308
309
  result
@@ -354,6 +355,14 @@ module GoodJob
354
355
  (finished_at || Time.zone.now) - performed_at if performed_at
355
356
  end
356
357
 
358
+ # Destroys this execution and all executions within the same job
359
+ def destroy_job
360
+ @_destroy_job = true
361
+ destroy!
362
+ ensure
363
+ @_destroy_job = false
364
+ end
365
+
357
366
  private
358
367
 
359
368
  def active_job_data
@@ -379,7 +388,7 @@ module GoodJob
379
388
  end
380
389
  handled_error ||= current_thread.error_on_retry || current_thread.error_on_discard
381
390
 
382
- ExecutionResult.new(value: value, handled_error: handled_error)
391
+ ExecutionResult.new(value: value, handled_error: handled_error, retried: current_thread.error_on_retry.present?)
383
392
  rescue StandardError => e
384
393
  ExecutionResult.new(value: nil, unhandled_error: e)
385
394
  end
@@ -8,14 +8,18 @@ module GoodJob
8
8
  attr_reader :handled_error
9
9
  # @return [Exception, nil]
10
10
  attr_reader :unhandled_error
11
+ # @return [Exception, nil]
12
+ attr_reader :retried
13
+ alias retried? retried
11
14
 
12
15
  # @param value [Object, nil]
13
16
  # @param handled_error [Exception, nil]
14
17
  # @param unhandled_error [Exception, nil]
15
- def initialize(value:, handled_error: nil, unhandled_error: nil)
18
+ def initialize(value:, handled_error: nil, unhandled_error: nil, retried: false)
16
19
  @value = value
17
20
  @handled_error = handled_error
18
21
  @unhandled_error = unhandled_error
22
+ @retried = retried
19
23
  end
20
24
  end
21
25
  end
@@ -55,12 +55,12 @@ module GoodJob
55
55
  scope :queued, -> { where(finished_at: nil).where('COALESCE(scheduled_at, created_at) <= ?', DateTime.current).joins_advisory_locks.where(pg_locks: { locktype: nil }) }
56
56
  # Advisory locked and executing
57
57
  scope :running, -> { where(finished_at: nil).joins_advisory_locks.where.not(pg_locks: { locktype: nil }) }
58
+ # Finished executing (succeeded or discarded)
59
+ scope :finished, -> { where.not(finished_at: nil).where(retried_good_job_id: nil) }
58
60
  # Completed executing successfully
59
- scope :finished, -> { not_discarded.where.not(finished_at: nil) }
61
+ scope :succeeded, -> { finished.where(error: nil) }
60
62
  # Errored but will not be retried
61
- scope :discarded, -> { where.not(finished_at: nil).where.not(error: nil) }
62
- # Not errored
63
- scope :not_discarded, -> { where(error: nil) }
63
+ scope :discarded, -> { finished.where.not(error: nil) }
64
64
 
65
65
  # The job's ActiveJob UUID
66
66
  # @return [String]
@@ -115,7 +115,7 @@ module GoodJob
115
115
  aj_count = serialized_params.fetch('executions', 0)
116
116
  # The execution count within serialized_params is not updated
117
117
  # once the underlying execution has been executed.
118
- if status.in? [:discarded, :finished, :running]
118
+ if status.in? [:discarded, :succeeded, :running]
119
119
  aj_count + 1
120
120
  else
121
121
  aj_count
@@ -154,6 +154,24 @@ module GoodJob
154
154
  end
155
155
  end
156
156
 
157
+ # Tests whether the job has finished (succeeded or discarded).
158
+ # @return [Boolean]
159
+ def finished?
160
+ finished_at.present? && retried_good_job_id.nil?
161
+ end
162
+
163
+ # Tests whether the job has finished but with an error.
164
+ # @return [Boolean]
165
+ def discarded?
166
+ finished? && error.present?
167
+ end
168
+
169
+ # Tests whether the job has finished without error
170
+ # @return [Boolean]
171
+ def succeeded?
172
+ finished? && !discarded?
173
+ end
174
+
157
175
  # Retry a job that has errored and been discarded.
158
176
  # This action will create a new {Execution} record for the job.
159
177
  # @return [ActiveJob::Base]
@@ -75,7 +75,7 @@
75
75
  <span class="font-monospace fw-bold"><%= job.priority %></span>
76
76
  </div>
77
77
  <div class="col-1 text-center">
78
- <% if job.executions_count > 0 && job.status != :finished %>
78
+ <% if job.executions_count > 0 && job.status != :succeeded %>
79
79
  <%= tag.span job.executions_count, class: "badge rounded-pill bg-danger", data: {
80
80
  bs_toggle: "popover",
81
81
  bs_trigger: "hover focus click",
@@ -118,7 +118,7 @@
118
118
  <% end %>
119
119
  </li>
120
120
  <li>
121
- <%= link_to job_path(job.id), method: :delete, class: "dropdown-item #{'disabled' unless job.status.in? [:discarded, :finished]}", title: "Destroy job", data: { confirm: "Confirm destroy", disable: true } do %>
121
+ <%= link_to job_path(job.id), method: :delete, class: "dropdown-item #{'disabled' unless job.status.in? [:discarded, :succeeded]}", title: "Destroy job", data: { confirm: "Confirm destroy", disable: true } do %>
122
122
  <%= render_icon "trash" %>
123
123
  Destroy
124
124
  <% end %>
@@ -47,7 +47,7 @@
47
47
  <% end %>
48
48
  <% end %>
49
49
 
50
- <% if @job.status.in? [:discarded, :finished] %>
50
+ <% if @job.status.in? [:discarded, :succeeded] %>
51
51
  <%= button_to job_path(@job.id), method: :delete, class: "btn btn-sm btn-outline-primary", form_class: "d-inline-block", aria: { label: "Destroy job" }, title: "Destroy job", data: { confirm: "Confirm destroy" } do %>
52
52
  <%= render_icon "trash" %>
53
53
  Destroy
@@ -58,11 +58,11 @@ en:
58
58
  processes: Processes
59
59
  status:
60
60
  discarded: Discarded
61
- finished: Finished
62
61
  queued: Queued
63
62
  retried: Retried
64
63
  running: Running
65
64
  scheduled: Scheduled
65
+ succeeded: Succeeded
66
66
  number:
67
67
  format:
68
68
  delimiter: ","
@@ -58,11 +58,11 @@ es:
58
58
  processes: Procesos
59
59
  status:
60
60
  discarded: Descartado
61
- finished: Acabado
62
61
  queued: Puesto en cola
63
62
  retried: reintentado
64
63
  running: Corriendo
65
64
  scheduled: Programado
65
+ succeeded: Acierto
66
66
  number:
67
67
  format:
68
68
  delimiter: " "
@@ -58,11 +58,11 @@ nl:
58
58
  processes: Processen
59
59
  status:
60
60
  discarded: weggegooid
61
- finished: Afgewerkt
62
61
  queued: In de wachtrij
63
62
  retried: Opnieuw geprobeerd
64
63
  running: Rennen
65
64
  scheduled: Gepland
65
+ succeeded: Geslaagd
66
66
  number:
67
67
  format:
68
68
  delimiter: "."
@@ -82,11 +82,11 @@ ru:
82
82
  processes: Процессы
83
83
  status:
84
84
  discarded: Отброшено
85
- finished: Законченный
86
85
  queued: В очереди
87
86
  retried: Повторная попытка
88
87
  running: Бег
89
88
  scheduled: по расписанию
89
+ succeeded: удалось
90
90
  number:
91
91
  format:
92
92
  delimiter: " "
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
  module GoodJob
3
3
  # GoodJob gem version.
4
- VERSION = '3.4.7'
4
+ VERSION = '3.5.0'
5
5
  end
data/lib/good_job.rb CHANGED
@@ -57,7 +57,7 @@ module GoodJob
57
57
  # By default, GoodJob deletes job records after the job is completed successfully.
58
58
  # If you want to preserve jobs for latter inspection, set this to +true+.
59
59
  # If you want to preserve only jobs that finished with error for latter inspection, set this to +:on_unhandled_error+.
60
- # @return [Boolean, nil]
60
+ # @return [Boolean, Symbol, nil]
61
61
  mattr_accessor :preserve_job_records, default: true
62
62
 
63
63
  # @!attribute [rw] retry_on_unhandled_error
@@ -157,7 +157,7 @@ module GoodJob
157
157
 
158
158
  ActiveSupport::Notifications.instrument("cleanup_preserved_jobs.good_job", { older_than: older_than, timestamp: timestamp }) do |payload|
159
159
  old_jobs = GoodJob::Job.where('finished_at <= ?', timestamp)
160
- old_jobs = old_jobs.not_discarded unless include_discarded
160
+ old_jobs = old_jobs.succeeded unless include_discarded
161
161
  old_jobs_count = old_jobs.count
162
162
 
163
163
  GoodJob::Execution.where(job: old_jobs).delete_all
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: 3.4.7
4
+ version: 3.5.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: 2022-10-06 00:00:00.000000000 Z
11
+ date: 2022-10-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activejob
@@ -252,16 +252,16 @@ dependencies:
252
252
  name: puma
253
253
  requirement: !ruby/object:Gem::Requirement
254
254
  requirements:
255
- - - ">="
255
+ - - "~>"
256
256
  - !ruby/object:Gem::Version
257
- version: '0'
257
+ version: '5.6'
258
258
  type: :development
259
259
  prerelease: false
260
260
  version_requirements: !ruby/object:Gem::Requirement
261
261
  requirements:
262
- - - ">="
262
+ - - "~>"
263
263
  - !ruby/object:Gem::Version
264
- version: '0'
264
+ version: '5.6'
265
265
  - !ruby/object:Gem::Dependency
266
266
  name: rspec-rails
267
267
  requirement: !ruby/object:Gem::Requirement