class Procrastinator::TaskMetaData

TaskMetaData objects are State Patterns that record information about the work done on a particular task.

It contains the specific information needed to run a task instance. Users define a task class, which describes the “how” of a task and TaskMetaData represents the “what” and “when”.

It contains task-specific data, timing information, and error records.

All of its state is read-only.

@author Robin Miller

@!attribute [r] :id

@return [Integer] the unique identifier for this task

@!attribute [r] :run_at

@return [Integer] Linux epoch timestamp of when to attempt this task next

@!attribute [r] :initial_run_at

@return [Integer] Linux epoch timestamp of the original value for run_at

@!attribute [r] :expire_at

@return [Integer] Linux epoch timestamp of when to consider this task obsolete

@!attribute [r] :attempts

@return [Integer] The number of times this task has been attempted

@!attribute [r] :last_error

@return [String] The message and stack trace of the error encountered on the most recent failed attempt

@!attribute [r] :last_fail_at

@return [Integer] Linux epoch timestamp of when the last_error was recorded

@!attribute [r] :data

@return [String] User-provided data serialized to string using YAML

Constants

EXPECTED_DATA

These are the attributes expected to be in the persistence mechanism

Public Class Methods

new(id: nil, run_at: nil, initial_run_at: nil, expire_at: nil, attempts: 0, last_error: nil, last_fail_at: nil, data: nil) click to toggle source
# File lib/procrastinator/task_meta_data.rb, line 37
def initialize(id: nil,
               run_at: nil,
               initial_run_at: nil,
               expire_at: nil,
               attempts: 0,
               last_error: nil,
               last_fail_at: nil,
               data: nil)
   @id             = id
   @run_at         = run_at.nil? ? nil : run_at.to_i
   @initial_run_at = initial_run_at.to_i
   @expire_at      = expire_at.nil? ? nil : expire_at.to_i
   @attempts       = attempts || 0
   @last_error     = last_error
   @last_fail_at   = last_fail_at
   @data           = data ? YAML.safe_load(data, [Symbol, Date]) : nil
end

Public Instance Methods

add_attempt() click to toggle source
# File lib/procrastinator/task_meta_data.rb, line 59
def add_attempt
   @attempts += 1
end
clear_fails() click to toggle source
# File lib/procrastinator/task_meta_data.rb, line 63
def clear_fails
   @last_error   = nil
   @last_fail_at = nil
end
expired?() click to toggle source
# File lib/procrastinator/task_meta_data.rb, line 78
def expired?
   !@expire_at.nil? && Time.now.to_i > @expire_at
end
fail(msg, final: false) click to toggle source
# File lib/procrastinator/task_meta_data.rb, line 68
def fail(msg, final: false)
   @last_fail_at = Time.now.to_i
   @last_error   = msg
   @run_at       = nil if final
end
final_fail?(queue) click to toggle source
# File lib/procrastinator/task_meta_data.rb, line 74
def final_fail?(queue)
   too_many_fails?(queue) || expired?
end
init_task(queue) click to toggle source
# File lib/procrastinator/task_meta_data.rb, line 55
def init_task(queue)
   @data ? queue.task_class.new(@data) : queue.task_class.new
end
reschedule() click to toggle source

TODO: This cop for ** is currently incorrect. This disable can be removed once they fix it. rubocop:disable Layout/SpaceAroundOperators

# File lib/procrastinator/task_meta_data.rb, line 98
def reschedule
   # (30 + n_attempts^4) seconds is chosen to rapidly expand
   # but with the baseline of 30s to avoid hitting the disk too frequently.
   @run_at += 30 + (@attempts ** 4) unless @run_at.nil?
end
runnable?() click to toggle source
# File lib/procrastinator/task_meta_data.rb, line 86
def runnable?
   !(@run_at.nil? || Time.now.to_i < @run_at)
end
serialized_data() click to toggle source

rubocop:enable Layout/SpaceAroundOperators

# File lib/procrastinator/task_meta_data.rb, line 106
def serialized_data
   YAML.dump(@data)
end
successful?() click to toggle source
# File lib/procrastinator/task_meta_data.rb, line 90
def successful?
   raise 'you cannot check for success before running #work' if !expired? && @attempts <= 0

   !expired? && @last_error.nil? && @last_fail_at.nil?
end
to_h() click to toggle source
# File lib/procrastinator/task_meta_data.rb, line 114
def to_h
   {id:             @id,
    run_at:         @run_at,
    initial_run_at: @initial_run_at,
    expire_at:      @expire_at,
    attempts:       @attempts,
    last_fail_at:   @last_fail_at,
    last_error:     @last_error,
    data:           serialized_data}
end
too_many_fails?(queue) click to toggle source
# File lib/procrastinator/task_meta_data.rb, line 82
def too_many_fails?(queue)
   !queue.max_attempts.nil? && @attempts >= queue.max_attempts
end
verify_expiry!() click to toggle source
# File lib/procrastinator/task_meta_data.rb, line 110
def verify_expiry!
   raise TaskExpiredError, "task is over its expiry time of #{ @expire_at }" if expired?
end