lib/good_job/execution.rb in good_job-2.14.4 vs lib/good_job/execution.rb in good_job-2.15.0

- old
+ new

@@ -86,19 +86,19 @@ # @!method priority_ordered # @!scope class # @return [ActiveRecord::Relation] scope :priority_ordered, -> { order('priority DESC NULLS LAST') } - # Order jobs by scheduled (unscheduled or soonest first). + # Order jobs by scheduled or created (oldest first). # @!method schedule_ordered # @!scope class # @return [ActiveRecord::Relation] scope :schedule_ordered, -> { order(Arel.sql('COALESCE(scheduled_at, created_at) ASC')) } # Get Jobs were completed before the given timestamp. If no timestamp is # provided, get all jobs that have been completed. By default, GoodJob - # deletes jobs after they are completed and this will find no jobs. + # destroys jobs after they are completed and this will find no jobs. # However, if you have changed {GoodJob.preserve_job_records}, this may # find completed Jobs. # @!method finished(timestamp = nil) # @!scope class # @param timestamp (Float) @@ -268,9 +268,68 @@ def active_job ActiveJob::Base.deserialize(active_job_data).tap do |aj| aj.send(:deserialize_arguments_if_needed) end + end + + # There are 3 buckets of non-overlapping statuses: + # 1. The job will be executed + # - queued: The job will execute immediately when an execution thread becomes available. + # - scheduled: The job is scheduled to execute in the future. + # - retried: The job previously errored on execution and will be re-executed in the future. + # 2. The job is being executed + # - running: the job is actively being executed by an execution thread + # 3. The job will not execute + # - finished: The job executed successfully + # - discarded: The job previously errored on execution and will not be re-executed in the future. + # + # @return [Symbol] + def status + if finished_at.present? + if error.present? + :discarded + else + :finished + end + elsif (scheduled_at || created_at) > DateTime.current + if serialized_params.fetch('executions', 0) > 1 + :retried + else + :scheduled + end + elsif running? + :running + else + :queued + end + end + + def running? + performed_at? && !finished_at? + end + + def number + serialized_params.fetch('executions', 0) + 1 + end + + # The last relevant timestamp for this execution + def last_status_at + finished_at || performed_at || scheduled_at || created_at + end + + # Time between when this job was expected to run and when it started running + def queue_latency + now = Time.zone.now + expected_start = scheduled_at || created_at + actual_start = performed_at || now + + actual_start - expected_start unless expected_start >= now + end + + # Time between when this job started and finished + def runtime_latency + (finished_at || Time.zone.now) - performed_at if performed_at end private def active_job_data