good_job 3.0.0 → 3.1.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: a4f4e14bae83760bdeb35557a727116d053e47a9b7dbf501914606dbc45c2ef7
4
- data.tar.gz: c06e9165b7ac5d87af0ab75291fedd0194018752f34332c1a16930ddca53e3dd
3
+ metadata.gz: bc6e3cffa2189a101181b7ceb278de97ded27d14dd6da915ea8fe3729907dd88
4
+ data.tar.gz: 0504d2f2efd09d1d52669597e364f62b69edc739d3c76b8bcfdd1933ea7cb8da
5
5
  SHA512:
6
- metadata.gz: 949cfcf1506ff658666113e035a875ed4ab44fa3e2c674e4d5d1440bf484d39793a1ee595ae0cb6f719136ce5541aae09a7fc2d66a049ea1bcf973b0165dc8a4
7
- data.tar.gz: 9c9ff56251e01d60823a50f4edcea74034a36ef93929cf59adc588273da86d1e04f67c1b25d7d35efecda9309acf7f49f81d29fbc7f94249be0e3732087f9081
6
+ metadata.gz: c10f675a3635f481e370502828ed0902aff3464e19f161bf5f300463a2671ecac09643eb0943030eda30163171b67986b0f9e31ca423ad5da9e4ffd5b23a7df7
7
+ data.tar.gz: 3ab12e91adb910040a4007140054cc048a0f83e34e54ee649e52ea673a27b95cfb267b56fae98a7605616e4c3f55d17af403c99bf9ba2a5d504dffdd917a7cbb
data/CHANGELOG.md CHANGED
@@ -1,5 +1,67 @@
1
1
  # Changelog
2
2
 
3
+ ## [v3.1.0](https://github.com/bensheldon/good_job/tree/v3.1.0) (2022-07-11)
4
+
5
+ [Full Changelog](https://github.com/bensheldon/good_job/compare/v3.0.2...v3.1.0)
6
+
7
+ **Implemented enhancements:**
8
+
9
+ - Improve Dashboard display of parameters \(CronEntry kwargs; Process configuration; Job and Execution database values\) [\#662](https://github.com/bensheldon/good_job/pull/662) ([bensheldon](https://github.com/bensheldon))
10
+
11
+ **Fixed bugs:**
12
+
13
+ - Don't delegate `GoodJob::Job#status` to executions to avoid race condition [\#661](https://github.com/bensheldon/good_job/pull/661) ([bensheldon](https://github.com/bensheldon))
14
+
15
+ **Closed issues:**
16
+
17
+ - How to suppress repetitive logs in development? [\#658](https://github.com/bensheldon/good_job/issues/658)
18
+ - 500 Internal Server Error Exception in web interface trying to view running jobs [\#656](https://github.com/bensheldon/good_job/issues/656)
19
+ - Cron schedule page in dashboard not showing kwargs [\#608](https://github.com/bensheldon/good_job/issues/608)
20
+ - Paralelism x database connections [\#569](https://github.com/bensheldon/good_job/issues/569)
21
+
22
+ **Merged pull requests:**
23
+
24
+ - Show job/cron/process counts in the Navbar [\#663](https://github.com/bensheldon/good_job/pull/663) ([bensheldon](https://github.com/bensheldon))
25
+ - Dequeing should be first-in first-out [\#651](https://github.com/bensheldon/good_job/pull/651) ([jrochkind](https://github.com/jrochkind))
26
+
27
+ ## [v3.0.2](https://github.com/bensheldon/good_job/tree/v3.0.2) (2022-07-10)
28
+
29
+ [Full Changelog](https://github.com/bensheldon/good_job/compare/v3.0.1...v3.0.2)
30
+
31
+ **Fixed bugs:**
32
+
33
+ - Copy forward concurrency key value when retrying a job, rather than regenerating it [\#622](https://github.com/bensheldon/good_job/issues/622)
34
+ - All concurrency controlled jobs throw exceptions and are rescheduled if they are called using perform\_now [\#591](https://github.com/bensheldon/good_job/issues/591)
35
+
36
+ **Closed issues:**
37
+
38
+ - Queue config not respecting limits [\#659](https://github.com/bensheldon/good_job/issues/659)
39
+ - UI engine does not work without explicit require [\#646](https://github.com/bensheldon/good_job/issues/646)
40
+ - Should `:inline` adapter mode retry jobs? [\#611](https://github.com/bensheldon/good_job/issues/611)
41
+ - Error Job Not Preserved [\#594](https://github.com/bensheldon/good_job/issues/594)
42
+ - Jobs never get run... [\#516](https://github.com/bensheldon/good_job/issues/516)
43
+ - Release GoodJob 3.0 [\#507](https://github.com/bensheldon/good_job/issues/507)
44
+ - Improve security of Gem releases [\#422](https://github.com/bensheldon/good_job/issues/422)
45
+
46
+ **Merged pull requests:**
47
+
48
+ - Preserve initial concurrency key when retrying jobs [\#657](https://github.com/bensheldon/good_job/pull/657) ([bensheldon](https://github.com/bensheldon))
49
+ - Add Dashboard troubleshooting note to explicitly require the engine [\#654](https://github.com/bensheldon/good_job/pull/654) ([bensheldon](https://github.com/bensheldon))
50
+ - Removes wrong parentheses [\#653](https://github.com/bensheldon/good_job/pull/653) ([esasse](https://github.com/esasse))
51
+
52
+ ## [v3.0.1](https://github.com/bensheldon/good_job/tree/v3.0.1) (2022-07-02)
53
+
54
+ [Full Changelog](https://github.com/bensheldon/good_job/compare/v3.0.0...v3.0.1)
55
+
56
+ **Closed issues:**
57
+
58
+ - ERROR: relation "good\_jobs" does not exist at character 454 [\#308](https://github.com/bensheldon/good_job/issues/308)
59
+
60
+ **Merged pull requests:**
61
+
62
+ - 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))
63
+ - Create codeql-analysis.yml [\#648](https://github.com/bensheldon/good_job/pull/648) ([bensheldon](https://github.com/bensheldon))
64
+
3
65
  ## [v3.0.0](https://github.com/bensheldon/good_job/tree/v3.0.0) (2022-06-26)
4
66
 
5
67
  [Full Changelog](https://github.com/bensheldon/good_job/compare/v2.99.0...v3.0.0)
@@ -1011,7 +1073,6 @@
1011
1073
 
1012
1074
  **Closed issues:**
1013
1075
 
1014
- - ERROR: relation "good\_jobs" does not exist at character 454 [\#308](https://github.com/bensheldon/good_job/issues/308)
1015
1076
  - Add Frozen String Literal to all files [\#298](https://github.com/bensheldon/good_job/issues/298)
1016
1077
  - Support for good\_job without Rails? [\#295](https://github.com/bensheldon/good_job/issues/295)
1017
1078
 
data/README.md CHANGED
@@ -370,6 +370,16 @@ GoodJob includes a Dashboard as a mountable `Rails::Engine`.
370
370
 
371
371
  See more at [Monitor and preserve worked jobs](#monitor-and-preserve-worked-jobs)
372
372
 
373
+ **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.
374
+
375
+ ```ruby
376
+ # config/application.rb
377
+ require_relative 'boot'
378
+ require 'rails/all'
379
+ require 'good_job/engine' # <= Add this line
380
+ # ...
381
+ ```
382
+
373
383
  #### API-only Rails applications
374
384
 
375
385
  API-only Rails applications may not have all of the required Rack middleware for the GoodJob Dashboard to function. To re-add the middlware:
@@ -713,7 +723,7 @@ Each GoodJob execution thread requires its own database connection that is autom
713
723
 
714
724
  ```yaml
715
725
  # config/database.yml
716
- pool: <%= ENV.fetch("RAILS_MAX_THREADS", 5).to_i + 3 + (ENV.fetch("GOOD_JOB_MAX_THREADS", 5).to_i %>
726
+ pool: <%= ENV.fetch("RAILS_MAX_THREADS", 5).to_i + 3 + ENV.fetch("GOOD_JOB_MAX_THREADS", 5).to_i %>
717
727
  ```
718
728
 
719
729
  To calculate the total number of the database connections you'll need:
@@ -56,7 +56,7 @@ module GoodJob
56
56
  end
57
57
 
58
58
  def show
59
- @job = Job.find(params[:id])
59
+ @job = Job.includes_advisory_locks.find(params[:id])
60
60
  end
61
61
 
62
62
  def discard
@@ -38,7 +38,7 @@
38
38
  </div>
39
39
  <% end %>
40
40
  <div>
41
- <%= tag.pre JSON.pretty_generate(execution.serialized_params), id: dom_id(execution, "params"), class: "collapse bg-light card card-body p-3 my-3" %>
41
+ <%= tag.pre JSON.pretty_generate(execution.display_serialized_params), id: dom_id(execution, "params"), class: "collapse bg-light card card-body p-3 my-3" %>
42
42
  </div>
43
43
  <% end %>
44
44
  <% end %>
@@ -13,7 +13,7 @@
13
13
  <th>Executions</th>
14
14
  <th>Error</th>
15
15
  <th>
16
- ActiveJob Params&nbsp;
16
+ Parameters&nbsp;
17
17
  <%= tag.button "Toggle", type: "button", class: "btn btn-sm btn-outline-primary", role: "button",
18
18
  data: { bs_toggle: "collapse", bs_target: ".job-params" },
19
19
  aria: { expanded: false, controls: jobs.map { |job| "##{dom_id(job, "params")}" }.join(" ") }
@@ -71,7 +71,7 @@
71
71
  data: { bs_toggle: "collapse", bs_target: "##{dom_id(job, 'params')}" },
72
72
  aria: { expanded: false, controls: dom_id(job, "params") }
73
73
  %>
74
- <%= tag.pre JSON.pretty_generate(job.serialized_params), id: dom_id(job, "params"), class: "collapse job-params" %>
74
+ <%= tag.pre JSON.pretty_generate(job.display_serialized_params), id: dom_id(job, "params"), class: "collapse job-params" %>
75
75
  </td>
76
76
  <td>
77
77
  <div class="text-nowrap">
@@ -54,4 +54,4 @@
54
54
  <%= tag.pre @job.serialized_params["arguments"].map(&:inspect).join(', ') %>
55
55
  </div>
56
56
 
57
- <%= render 'executions', executions: @job.executions.reverse %>
57
+ <%= render 'executions', executions: @job.executions.includes_advisory_locks.reverse %>
@@ -11,7 +11,7 @@
11
11
  <li class="nav-item">
12
12
  <%= link_to url_for({state: name}), class: "nav-link #{"active" if params[:state] == name}" do %>
13
13
  <%= t(name, scope: 'good_job.status') %>
14
- <span class="badge bg-primary rounded-pill <%= "bg-secondary" if count == 0 %>"><%= count %></span>
14
+ <span class="badge bg-primary rounded-pill <%= "bg-secondary" if count == 0 %>"><%= number_with_delimiter(count) %></span>
15
15
  <% end %>
16
16
  </li>
17
17
  <% end %>
@@ -8,13 +8,25 @@
8
8
  <div class="collapse navbar-collapse" id="navbarSupportedContent">
9
9
  <ul class="navbar-nav me-auto">
10
10
  <li class="nav-item">
11
- <%= link_to t(".jobs"), jobs_path, class: ["nav-link", ("active" if controller_name == 'jobs')] %>
11
+ <%= link_to jobs_path, class: ["nav-link", ("active" if controller_name == 'jobs')] do %>
12
+ <%= t(".jobs") %>
13
+ <% jobs_count = GoodJob::Job.count %>
14
+ <span class="badge bg-secondary rounded-pill"><%= number_to_human(jobs_count) %></span>
15
+ <% end %>
12
16
  </li>
13
17
  <li class="nav-item">
14
- <%= link_to t(".cron_schedules"), cron_entries_path, class: ["nav-link", ("active" if controller_name == 'cron_entries')] %>
18
+ <%= link_to cron_entries_path, class: ["nav-link", ("active" if controller_name == 'cron_entries')] do %>
19
+ <%= t(".cron_schedules") %>
20
+ <% cron_entries_count = GoodJob::CronEntry.all.size %>
21
+ <span class="badge bg-secondary rounded-pill"><%= cron_entries_count %></span>
22
+ <% end %>
15
23
  </li>
16
24
  <li class="nav-item">
17
- <%= link_to t(".processes"), processes_path, class: ["nav-link", ("active" if controller_name == 'processes')] %>
25
+ <%= link_to processes_path, class: ["nav-link", ("active" if controller_name == 'processes')] do %>
26
+ <%= t(".processes") %>
27
+ <% processes_count = GoodJob::Process.count %>
28
+ <span class="badge bg-secondary rounded-pill <%= "bg-danger" if processes_count == 0 %>"><%= processes_count %></span>
29
+ <% end %>
18
30
  </li>
19
31
  </ul>
20
32
  <div class="nav-item pe-2">
@@ -63,3 +63,22 @@ en:
63
63
  retried: Retried
64
64
  running: Running
65
65
  scheduled: Scheduled
66
+ number:
67
+ format:
68
+ delimiter: ","
69
+ separator: "."
70
+ human:
71
+ decimal_units:
72
+ format: "%n%u"
73
+ units:
74
+ billion: B
75
+ hundred: ''
76
+ million: M
77
+ quadrillion: Q
78
+ thousand: K
79
+ trillion: T
80
+ unit: ''
81
+ format:
82
+ delimiter: ","
83
+ precision: 3
84
+ separator: "."
@@ -63,3 +63,22 @@ es:
63
63
  retried: reintentado
64
64
  running: Corriendo
65
65
  scheduled: Programado
66
+ number:
67
+ format:
68
+ delimiter: " "
69
+ separator: ","
70
+ human:
71
+ decimal_units:
72
+ format: "%n%u"
73
+ units:
74
+ billion: B
75
+ hundred: ''
76
+ million: M
77
+ quadrillion: q
78
+ thousand: k
79
+ trillion: T
80
+ unit: ''
81
+ format:
82
+ delimiter: " "
83
+ precision: 3
84
+ separator: ","
@@ -63,3 +63,22 @@ nl:
63
63
  retried: Opnieuw geprobeerd
64
64
  running: Rennen
65
65
  scheduled: Gepland
66
+ number:
67
+ format:
68
+ delimiter: "."
69
+ separator: ","
70
+ human:
71
+ decimal_units:
72
+ format: "%n%u"
73
+ units:
74
+ billion: B
75
+ hundred: ''
76
+ million: M
77
+ quadrillion: Q
78
+ thousand: K
79
+ trillion: T
80
+ unit: ''
81
+ format:
82
+ delimiter: "."
83
+ precision: 3
84
+ separator: ","
@@ -87,3 +87,22 @@ ru:
87
87
  retried: Повторная попытка
88
88
  running: Бег
89
89
  scheduled: по расписанию
90
+ number:
91
+ format:
92
+ delimiter: " "
93
+ separator: ","
94
+ human:
95
+ decimal_units:
96
+ format: "%n%u"
97
+ units:
98
+ billion: Б
99
+ hundred: ''
100
+ million: М
101
+ quadrillion: Q
102
+ thousand: К
103
+ trillion: Т
104
+ unit: ''
105
+ format:
106
+ delimiter: " "
107
+ precision: 3
108
+ separator: ","
@@ -10,8 +10,18 @@ module GoodJob
10
10
  end
11
11
  end
12
12
 
13
+ module Prepends
14
+ def deserialize(job_data)
15
+ super
16
+ self.good_job_concurrency_key = job_data['good_job_concurrency_key']
17
+ end
18
+ end
19
+
13
20
  included do
21
+ prepend Prepends
22
+
14
23
  class_attribute :good_job_concurrency_config, instance_accessor: false, default: {}
24
+ attr_writer :good_job_concurrency_key
15
25
 
16
26
  around_enqueue do |job, block|
17
27
  # Don't attempt to enforce concurrency limits with other queue adapters.
@@ -27,6 +37,8 @@ module GoodJob
27
37
  (total_limit.present? && (0...Float::INFINITY).cover?(total_limit))
28
38
  next(block.call) unless has_limit
29
39
 
40
+ # Only generate the concurrency key on the initial enqueue in case it is dynamic
41
+ job.good_job_concurrency_key ||= job._good_job_concurrency_key
30
42
  key = job.good_job_concurrency_key
31
43
  next(block.call) if key.blank?
32
44
 
@@ -80,7 +92,15 @@ module GoodJob
80
92
  end
81
93
  end
82
94
 
95
+ # Existing or dynamically generated concurrency key
96
+ # @return [Object] concurrency key
83
97
  def good_job_concurrency_key
98
+ @good_job_concurrency_key || _good_job_concurrency_key
99
+ end
100
+
101
+ # Generates the concurrency key from the configuration
102
+ # @return [Object] concurrency key
103
+ def _good_job_concurrency_key
84
104
  key = self.class.good_job_concurrency_config[:key]
85
105
  return if key.blank?
86
106
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
  module GoodJob
3
3
  # GoodJob gem version.
4
- VERSION = '3.0.0'
4
+ VERSION = '3.1.0'
5
5
  end
data/lib/good_job.rb CHANGED
@@ -145,7 +145,7 @@ module GoodJob
145
145
  old_jobs = old_jobs.not_discarded unless include_discarded
146
146
  old_jobs_count = old_jobs.count
147
147
 
148
- GoodJob::Execution.where(job: old_jobs).destroy_all
148
+ GoodJob::Execution.where(job: old_jobs).delete_all
149
149
  payload[:destroyed_records_count] = old_jobs_count
150
150
  end
151
151
  end
@@ -112,9 +112,11 @@ module GoodJob # :nodoc:
112
112
  class: job_class,
113
113
  cron: schedule,
114
114
  set: display_property(set),
115
- args: display_property(args),
116
115
  description: display_property(description),
117
- }
116
+ }.tap do |properties|
117
+ properties[:args] = display_property(args) if args.present?
118
+ properties[:kwargs] = display_property(kwargs) if kwargs.present?
119
+ end
118
120
  end
119
121
 
120
122
  private
@@ -88,6 +88,18 @@ module GoodJob
88
88
  # @return [ActiveRecord::Relation]
89
89
  scope :priority_ordered, -> { order('priority DESC NULLS LAST') }
90
90
 
91
+ # Order jobs by created_at, for first-in first-out
92
+ # @!method creation_ordered
93
+ # @!scope class
94
+ # @return [ActiveRecord:Relation]
95
+ scope :creation_ordered, -> { order('created_at ASC') }
96
+
97
+ # Order jobs for de-queueing
98
+ # @!method dequeue_ordered
99
+ # @!scope class
100
+ # @return [ActiveRecord:Relation]
101
+ scope :dequeue_ordered, -> { priority_ordered.creation_ordered }
102
+
91
103
  # Order jobs by scheduled or created (oldest first).
92
104
  # @!method schedule_ordered
93
105
  # @!scope class
@@ -154,7 +166,7 @@ module GoodJob
154
166
  # raised, if any (if the job raised, then the second array entry will be
155
167
  # +nil+). If there were no jobs to execute, returns +nil+.
156
168
  def self.perform_with_advisory_lock
157
- unfinished.priority_ordered.only_scheduled.limit(1).with_advisory_lock(unlock_session: true) do |executions|
169
+ unfinished.dequeue_ordered.only_scheduled.limit(1).with_advisory_lock(unlock_session: true) do |executions|
158
170
  execution = executions.first
159
171
  break if execution.blank?
160
172
  break :unlocked unless execution&.executable?
@@ -279,7 +291,9 @@ module GoodJob
279
291
  # @return [Symbol]
280
292
  def status
281
293
  if finished_at.present?
282
- if error.present?
294
+ if error.present? && retried_good_job_id.present?
295
+ :retried
296
+ elsif error.present? && retried_good_job_id.nil?
283
297
  :discarded
284
298
  else
285
299
  :finished
@@ -297,8 +311,20 @@ module GoodJob
297
311
  end
298
312
  end
299
313
 
314
+ # Return formatted serialized_params for display in the dashboard
315
+ # @return [Hash]
316
+ def display_serialized_params
317
+ serialized_params.merge({
318
+ _good_job: attributes.except('serialized_params', 'locktype', 'owns_advisory_lock'),
319
+ })
320
+ end
321
+
300
322
  def running?
301
- performed_at? && !finished_at?
323
+ if has_attribute?(:locktype)
324
+ self['locktype'].present?
325
+ else
326
+ advisory_locked?
327
+ end
302
328
  end
303
329
 
304
330
  def number
@@ -314,7 +340,7 @@ module GoodJob
314
340
  def queue_latency
315
341
  now = Time.zone.now
316
342
  expected_start = scheduled_at || created_at
317
- actual_start = performed_at || now
343
+ actual_start = performed_at || finished_at || now
318
344
 
319
345
  actual_start - expected_start unless expected_start >= now
320
346
  end
@@ -330,6 +356,7 @@ module GoodJob
330
356
  serialized_params.deep_dup
331
357
  .tap do |job_data|
332
358
  job_data["provider_job_id"] = id
359
+ job_data["good_job_concurrency_key"] = concurrency_key if concurrency_key
333
360
  end
334
361
  end
335
362
 
@@ -3,7 +3,8 @@ module GoodJob
3
3
  # ActiveRecord model that represents an +ActiveJob+ job.
4
4
  # There is not a table in the database whose discrete rows represents "Jobs".
5
5
  # The +good_jobs+ table is a table of individual {GoodJob::Execution}s that share the same +active_job_id+.
6
- # A single row from the +good_jobs+ table of executions is fetched to represent an Job
6
+ # A single row from the +good_jobs+ table of executions is fetched to represent a Job.
7
+ #
7
8
  class Job < BaseRecord
8
9
  include Filterable
9
10
  include Lockable
@@ -72,9 +73,51 @@ module GoodJob
72
73
  serialized_params['job_class']
73
74
  end
74
75
 
75
- # The status of the Job, based on the state of its most recent execution.
76
- # @return [Symbol]
77
- delegate :status, :last_status_at, to: :head_execution
76
+ def last_status_at
77
+ finished_at || performed_at || scheduled_at || created_at
78
+ end
79
+
80
+ def status
81
+ if finished_at.present?
82
+ if error.present? && retried_good_job_id.present?
83
+ :retried
84
+ elsif error.present? && retried_good_job_id.nil?
85
+ :discarded
86
+ else
87
+ :finished
88
+ end
89
+ elsif (scheduled_at || created_at) > DateTime.current
90
+ if serialized_params.fetch('executions', 0) > 1
91
+ :retried
92
+ else
93
+ :scheduled
94
+ end
95
+ elsif running?
96
+ :running
97
+ else
98
+ :queued
99
+ end
100
+ end
101
+
102
+ # Override #reload to add a custom scope to ensure the reloaded record is the head execution
103
+ # @return [Job]
104
+ def reload(options = nil)
105
+ self.class.connection.clear_query_cache
106
+
107
+ # override with the `where(retried_good_job_id: nil)` scope
108
+ override_query = self.class.where(retried_good_job_id: nil)
109
+ fresh_object =
110
+ if options && options[:lock]
111
+ self.class.unscoped { override_query.lock(options[:lock]).find(id) }
112
+ else
113
+ self.class.unscoped { override_query.find(id) }
114
+ end
115
+
116
+ @attributes = fresh_object.instance_variable_get(:@attributes)
117
+ @new_record = false
118
+ @previously_new_record = false
119
+ self
120
+ end
78
121
 
79
122
  # This job's most recent {Execution}
80
123
  # @param reload [Booelan] whether to reload executions
@@ -94,7 +137,7 @@ module GoodJob
94
137
  # The number of times this job has been executed, according to ActiveJob's serialized state.
95
138
  # @return [Numeric]
96
139
  def executions_count
97
- aj_count = head_execution.serialized_params.fetch('executions', 0)
140
+ aj_count = serialized_params.fetch('executions', 0)
98
141
  # The execution count within serialized_params is not updated
99
142
  # once the underlying execution has been executed.
100
143
  if status.in? [:discarded, :finished, :running]
@@ -114,7 +157,15 @@ module GoodJob
114
157
  # If the job has been retried, the error will be fetched from the previous {Execution} record.
115
158
  # @return [String]
116
159
  def recent_error
117
- head_execution.error || executions[-2]&.error
160
+ error || executions[-2]&.error
161
+ end
162
+
163
+ # Return formatted serialized_params for display in the dashboard
164
+ # @return [Hash]
165
+ def display_serialized_params
166
+ serialized_params.merge({
167
+ _good_job: attributes.except('serialized_params', 'locktype', 'owns_advisory_lock'),
168
+ })
118
169
  end
119
170
 
120
171
  # Tests whether the job is being executed right now.
@@ -192,7 +243,6 @@ module GoodJob
192
243
 
193
244
  raise ActionForStateMismatchError if execution.finished_at.present?
194
245
 
195
- execution = head_execution(reload: true)
196
246
  execution.update(scheduled_at: scheduled_at)
197
247
  end
198
248
  end
@@ -45,6 +45,8 @@ module GoodJob # :nodoc:
45
45
  hostname: Socket.gethostname,
46
46
  pid: ::Process.pid,
47
47
  proctitle: $PROGRAM_NAME,
48
+ preserve_job_records: GoodJob.preserve_job_records,
49
+ retry_on_unhandled_error: GoodJob.retry_on_unhandled_error,
48
50
  schedulers: GoodJob::Scheduler.instances.map(&:name),
49
51
  }
50
52
  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: 3.0.0
4
+ version: 3.1.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-06-26 00:00:00.000000000 Z
11
+ date: 2022-07-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activejob