Class: Procrastinator::TaskWorker

Inherits:
Object
  • Object
show all
Defined in:
lib/procrastinator/task_worker.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(id: nil, run_at: nil, initial_run_at: nil, expire_at: nil, attempts: 0, timeout: nil, max_attempts: nil, last_fail_at: nil, last_error: nil, task:, logger: Logger.new(StringIO.new)) ⇒ TaskWorker

Returns a new instance of TaskWorker.

Raises:



7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# File 'lib/procrastinator/task_worker.rb', line 7

def initialize(id: nil,
               run_at: nil,
               initial_run_at: nil,
               expire_at: nil,
               attempts: 0,
               timeout: nil,
               max_attempts: nil,
               last_fail_at: nil,
               last_error: nil,
               task:,
               logger: Logger.new(StringIO.new))
   @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
   @task           = YAML.load(task)
   @attempts       = attempts || 0
   @max_attempts   = max_attempts
   @timeout        = timeout
   @last_fail_at   = last_fail_at
   @last_error     = last_error
   @logger         = logger

   raise(MalformedTaskError.new('given task does not support #run method')) unless @task.respond_to? :run
   raise(ArgumentError.new('timeout cannot be negative')) if timeout && timeout < 0
end

Instance Attribute Details

#attemptsObject (readonly)

Returns the value of attribute attempts.



5
6
7
# File 'lib/procrastinator/task_worker.rb', line 5

def attempts
  @attempts
end

#expire_atObject (readonly)

Returns the value of attribute expire_at.



5
6
7
# File 'lib/procrastinator/task_worker.rb', line 5

def expire_at
  @expire_at
end

#idObject (readonly)

Returns the value of attribute id.



5
6
7
# File 'lib/procrastinator/task_worker.rb', line 5

def id
  @id
end

#initial_run_atObject (readonly)

Returns the value of attribute initial_run_at.



5
6
7
# File 'lib/procrastinator/task_worker.rb', line 5

def initial_run_at
  @initial_run_at
end

#last_errorObject (readonly)

Returns the value of attribute last_error.



5
6
7
# File 'lib/procrastinator/task_worker.rb', line 5

def last_error
  @last_error
end

#last_fail_atObject (readonly)

Returns the value of attribute last_fail_at.



5
6
7
# File 'lib/procrastinator/task_worker.rb', line 5

def last_fail_at
  @last_fail_at
end

#run_atObject (readonly)

Returns the value of attribute run_at.



5
6
7
# File 'lib/procrastinator/task_worker.rb', line 5

def run_at
  @run_at
end

#taskObject (readonly)

Returns the value of attribute task.



5
6
7
# File 'lib/procrastinator/task_worker.rb', line 5

def task
  @task
end

Instance Method Details

#expired?Boolean

Returns:

  • (Boolean)


83
84
85
# File 'lib/procrastinator/task_worker.rb', line 83

def expired?
   !@expire_at.nil? && Time.now.to_i > @expire_at
end

#successful?Boolean

Returns:

  • (Boolean)


71
72
73
74
75
76
77
# File 'lib/procrastinator/task_worker.rb', line 71

def successful?
   if !expired? && @attempts <= 0
      raise(RuntimeError, 'you cannot check for success before running #work')
   end

   @last_error.nil? && @last_fail_at.nil?
end

#to_hashObject



87
88
89
90
91
92
93
94
95
96
# File 'lib/procrastinator/task_worker.rb', line 87

def to_hash
   {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,
    task:           YAML.dump(@task)}
end

#too_many_fails?Boolean

Returns:

  • (Boolean)


79
80
81
# File 'lib/procrastinator/task_worker.rb', line 79

def too_many_fails?
   !@max_attempts.nil? && @attempts >= @max_attempts
end

#workObject



34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/procrastinator/task_worker.rb', line 34

def work
   @attempts += 1

   begin
      raise(TaskExpiredError.new("task is over its expiry time of #{@expire_at}")) if expired?

      Timeout::timeout(@timeout) do
         @task.run
      end

      try_hook(:success, @logger)

      @logger.debug("Task completed: #{YAML.dump(@task)}")

      @last_error   = nil
      @last_fail_at = nil
   rescue StandardError => e
      @last_fail_at = Time.now.to_i

      if too_many_fails? || expired?
         try_hook(:final_fail, @logger, e)

         @run_at     = nil
         @last_error = "#{expired? ? 'Task expired' : 'Task failed too many times'}: #{e.backtrace.join("\n")}"

         @logger.debug("Task failed permanently: #{YAML.dump(@task)}")
      else
         try_hook(:fail, @logger, e)

         @last_error = %Q[Task failed: #{e.message}\n#{e.backtrace.join("\n")}]
         @logger.debug("Task failed: #{YAML.dump(@task)}")

         reschedule
      end
   end
end