Class: GoodJob::Job
- Inherits:
-
BaseExecution
- Object
- ActiveRecord::Base
- BaseRecord
- BaseExecution
- GoodJob::Job
- Defined in:
- app/models/good_job/job.rb
Overview
Active Record model that represents an ActiveJob
job.
Constant Summary collapse
- ActionForStateMismatchError =
Raised when an inappropriate action is applied to a Job based on its state.
Class.new(StandardError)
- AdapterNotGoodJobError =
Raised when GoodJob is not configured as the Active Job Queue Adapter
Class.new(StandardError)
- DiscardJobError =
Attached to a Job’s Execution when the Job is discarded.
Class.new(StandardError)
- ActiveJobDeserializationError =
Raised when Active Job data cannot be deserialized
Class.new(StandardError)
Constants inherited from BaseExecution
BaseExecution::DEFAULT_PRIORITY, BaseExecution::DEFAULT_QUEUE_NAME, BaseExecution::ERROR_MESSAGE_SEPARATOR, BaseExecution::PreviouslyPerformedError
Constants included from ErrorEvents
ErrorEvents::ERROR_EVENTS, ErrorEvents::ERROR_EVENT_ENUMS
Constants included from AdvisoryLockable
AdvisoryLockable::RecordAlreadyAdvisoryLockedError
Class Method Summary collapse
-
.finished_before(timestamp) ⇒ ActiveRecord::Relation
Get Jobs finished before the given timestamp.
Instance Method Summary collapse
-
#_execution_id ⇒ String
Utility method to determine which execution record is used to represent this job.
-
#destroy_job ⇒ void
Destroy all of a discarded or finished job’s executions from the database so that it will no longer appear on the dashboard.
-
#discard_job(message) ⇒ void
Discard a job so that it will not be executed further.
-
#discarded? ⇒ Boolean
Tests whether the job has finished but with an error.
-
#display_error ⇒ String
Errors for the job to be displayed in the Dashboard.
-
#display_name ⇒ String
Used when displaying this job in the GoodJob dashboard.
-
#display_serialized_params ⇒ Hash
Return formatted serialized_params for display in the dashboard.
- #executions_count ⇒ Object
-
#finished? ⇒ Boolean
Tests whether the job has finished (succeeded or discarded).
-
#force_discard_job(message) ⇒ Object
Force discard a job so that it will not be executed further.
-
#recent_error ⇒ String
The most recent error message.
-
#reschedule_job(scheduled_at = Time.current) ⇒ void
Reschedule a scheduled job so that it executes immediately (or later) by the next available execution thread.
-
#retry_job ⇒ ActiveJob::Base
Retry a job that has errored and been discarded.
-
#running? ⇒ Boolean
Tests whether the job is being executed right now.
-
#succeeded? ⇒ Boolean
Tests whether the job has finished without error.
Methods inherited from BaseExecution
#active_job, active_job_id, build_for_enqueue, coalesce_scheduled_at_created_at, creation_ordered, dequeueing_ordered, enqueue, enqueue_args, #executable?, finished, format_error, job_class, #job_state, json_string, next_scheduled_at, #number, only_scheduled, params_execution_count, params_job_class, #perform, perform_with_advisory_lock, priority_ordered, #queue_latency, queue_ordered, queue_parser, queue_string, running, #runtime_latency, schedule_ordered, unfinished
Methods included from Reportable
Methods included from ErrorEvents
Methods included from AdvisoryLockable
#advisory_lock, #advisory_lock!, #advisory_locked?, #advisory_unlock, #advisory_unlock!, #advisory_unlocked?, #lockable_column_key, #lockable_key, #owns_advisory_lock?, #with_advisory_lock
Methods inherited from BaseRecord
bind_value, migrated?, migration_pending_warning!, with_logger_silenced
Class Method Details
.finished_before(timestamp) ⇒ ActiveRecord::Relation
Get Jobs finished before the given timestamp.
32 |
# File 'app/models/good_job/job.rb', line 32 scope :finished_before, ->() { where(arel_table['finished_at'].lteq(bind_value('finished_at', , ActiveRecord::Type::DateTime))) } |
Instance Method Details
#_execution_id ⇒ String
Utility method to determine which execution record is used to represent this job
198 199 200 |
# File 'app/models/good_job/job.rb', line 198 def _execution_id attributes['id'] end |
#destroy_job ⇒ void
This method returns an undefined value.
Destroy all of a discarded or finished job’s executions from the database so that it will no longer appear on the dashboard.
188 189 190 191 192 193 194 |
# File 'app/models/good_job/job.rb', line 188 def destroy_job with_advisory_lock do raise ActionForStateMismatchError if finished_at.blank? destroy end end |
#discard_job(message) ⇒ void
This method returns an undefined value.
Discard a job so that it will not be executed further. This action will add a DiscardJobError to the job’s Execution and mark it as finished.
161 162 163 164 165 |
# File 'app/models/good_job/job.rb', line 161 def discard_job() with_advisory_lock do _discard_job() end end |
#discarded? ⇒ Boolean
Tests whether the job has finished but with an error.
109 110 111 |
# File 'app/models/good_job/job.rb', line 109 def discarded? finished? && error.present? end |
#display_error ⇒ String
Errors for the job to be displayed in the Dashboard.
64 65 66 67 68 69 70 |
# File 'app/models/good_job/job.rb', line 64 def display_error return error if error.present? serialized_params.fetch('exception_executions', {}).map do |exception, count| "#{exception}: #{count}" end.join(', ') end |
#display_name ⇒ String
Used when displaying this job in the GoodJob dashboard.
82 83 84 |
# File 'app/models/good_job/job.rb', line 82 def display_name job_class end |
#display_serialized_params ⇒ Hash
Return formatted serialized_params for display in the dashboard
74 75 76 77 78 |
# File 'app/models/good_job/job.rb', line 74 def display_serialized_params serialized_params.merge({ _good_job: attributes.except('serialized_params', 'locktype', 'owns_advisory_lock'), }) end |
#executions_count ⇒ Object
86 87 88 |
# File 'app/models/good_job/job.rb', line 86 def executions_count super || 0 end |
#finished? ⇒ Boolean
Tests whether the job has finished (succeeded or discarded).
103 104 105 |
# File 'app/models/good_job/job.rb', line 103 def finished? finished_at.present? && retried_good_job_id.nil? end |
#force_discard_job(message) ⇒ Object
Force discard a job so that it will not be executed further. Force discard allows discarding a running job. This action will add a DiscardJobError to the job’s Execution and mark it as finished.
170 171 172 |
# File 'app/models/good_job/job.rb', line 170 def force_discard_job() _discard_job() end |
#recent_error ⇒ String
The most recent error message. If the job has been retried, the error will be fetched from the previous Execution record.
58 59 60 |
# File 'app/models/good_job/job.rb', line 58 def recent_error error || executions[-2]&.error end |
#reschedule_job(scheduled_at = Time.current) ⇒ void
This method returns an undefined value.
Reschedule a scheduled job so that it executes immediately (or later) by the next available execution thread.
177 178 179 180 181 182 183 184 |
# File 'app/models/good_job/job.rb', line 177 def reschedule_job(scheduled_at = Time.current) with_advisory_lock do reload raise ActionForStateMismatchError if finished_at.present? update(scheduled_at: scheduled_at) end end |
#retry_job ⇒ ActiveJob::Base
Retry a job that has errored and been discarded. This action will create a new Execution record for the job.
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 |
# File 'app/models/good_job/job.rb', line 122 def retry_job with_advisory_lock do reload active_job = self.active_job(ignore_deserialization_errors: true) raise ActiveJobDeserializationError if active_job.nil? raise AdapterNotGoodJobError unless active_job.class.queue_adapter.is_a? GoodJob::Adapter raise ActionForStateMismatchError if finished_at.blank? || error.blank? # Update the executions count because the previous execution will not have been preserved # Do not update `exception_executions` because that comes from rescue_from's arguments active_job.executions = (active_job.executions || 0) + 1 begin error_class, = error.split(ERROR_MESSAGE_SEPARATOR).map(&:strip) error = error_class.constantize.new() rescue StandardError error = StandardError.new(error) end new_active_job = nil GoodJob::CurrentThread.within do |current_thread| current_thread.job = self current_thread.retry_now = true self.class.transaction(joinable: false, requires_new: true) do new_active_job = active_job.retry_job(wait: 0, error: error) self.error_event = ERROR_EVENT_RETRIED if error save! end end new_active_job end end |
#running? ⇒ Boolean
Tests whether the job is being executed right now.
92 93 94 95 96 97 98 99 |
# File 'app/models/good_job/job.rb', line 92 def running? # Avoid N+1 Query: `.includes_advisory_locks` if has_attribute?(:locktype) self['locktype'].present? else advisory_locked? end end |
#succeeded? ⇒ Boolean
Tests whether the job has finished without error
115 116 117 |
# File 'app/models/good_job/job.rb', line 115 def succeeded? finished? && !discarded? end |