Class: Navvy::Job

Inherits:
ActiveRecord::Base
  • Object
show all
Includes:
DataMapper::Resource, MongoMapper::Document
Defined in:
lib/navvy/job.rb,
lib/navvy/job/sequel.rb,
lib/navvy/job/data_mapper.rb,
lib/navvy/job/mongo_mapper.rb,
lib/navvy/job/active_record.rb

Class Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Class Attribute Details

.keepFixnum, ...

If and how long the jobs should be kept. Will use the value stored in Navvy.configuration (defaults to false), or – for backwards compatibility – Navvy::Job.keep.

Returns:

  • (Fixnum, true, false)

    keep



25
26
27
# File 'lib/navvy/job.rb', line 25

def self.keep
  @keep || Navvy.configuration.keep_jobs
end

.limitInteger

Limit of jobs to be fetched at once. Will use the value stored in Navvy.configuration (defaults to 100), or – for backwards compatibility – Navvy::Job.limit.

Returns:

  • (Integer)

    limit



14
15
16
# File 'lib/navvy/job.rb', line 14

def self.limit
  @limit || Navvy.configuration.job_limit
end

.max_attemptsFixnum

How often should a job be retried? Will use the value stored in Navvy.configuration (defaults to 24), or – for backwards compatibility – Navvy::Job.max_attempts.

Returns:

  • (Fixnum)

    max_attempts



36
37
38
# File 'lib/navvy/job.rb', line 36

def self.max_attempts
  @max_attempts || Navvy.configuration.max_attempts
end

Class Method Details

.cleanuptrue, false

Clean up jobs that we don’t need to keep anymore. If Navvy::Job.keep is false it’ll delete every completed job, if it’s a timestamp it’ll only delete completed jobs that have passed their keeptime.

Returns:

  • (true, false)

    delete_all the result of the delete_all call



63
64
65
66
67
68
69
# File 'lib/navvy/job/sequel.rb', line 63

def self.cleanup
  if keep.is_a? Fixnum
    filter(:completed_at <= (Time.now - keep)).delete
  else
    filter(~{:completed_at => nil}).delete unless keep?
  end
end

.delete_alltrue, false

Deletes all jobs.

Returns:

  • (true, false)

    deleted?



76
77
78
# File 'lib/navvy/job/sequel.rb', line 76

def self.delete_all
  Navvy::Job.destroy
end

.enqueue(object, method_name, *args) ⇒ true, false

Add a job to the job queue.

Parameters:

  • object (Object)

    the object you want to run a method from

  • method_name (Symbol, String)

    the name of the method you want to run

  • arguments (*)

    optional arguments you want to pass to the method

Returns:

  • (true, false)


18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/navvy/job/sequel.rb', line 18

def self.enqueue(object, method_name, *args)
  options = {}
  if args.last.is_a?(Hash)
    options = args.last.delete(:job_options) || {}
    args.pop if args.last.empty?
  end

  insert(
    :object =>      object.to_s,
    :method_name => method_name.to_s,
    :arguments =>   args.to_yaml,
    :priority =>    options[:priority] || 0,
    :parent_id =>   options[:parent_id],
    :run_at =>      options[:run_at] || Time.now,
    :created_at =>  Time.now
  )
  order(:id.desc).first
end

.keep?true, false

Should the job be kept? Will calculate if the keeptime has passed if it’s probably a boolean.

Returns:

  • (true, false)

    keep



47
48
49
50
# File 'lib/navvy/job.rb', line 47

def self.keep?
  return (Time.now + self.keep) >= Time.now if self.keep.is_a? Fixnum
  self.keep
end

.next(limit = self.limit) ⇒ array?

Find the next available jobs in the queue. This will not include failed jobs (where :failed_at is not nil) and jobs that should run in the future (where :run_at is greater than the current time).

Navvy::Job.limit

jobs were found.

Parameters:

  • limit (Integer) (defaults to: self.limit)

    the limit of jobs to be fetched. Defaults to

Returns:

  • (array, nil)

    the next available jobs in an array or nil if no



48
49
50
51
52
53
54
# File 'lib/navvy/job/sequel.rb', line 48

def self.next(limit = self.limit)
  filter(
        (:run_at <= Time.now),
        {:failed_at    => nil, 
         :completed_at => nil}
  ).order(:priority.desc, :created_at).first(limit)
end

Instance Method Details

#argsarray

Get the job arguments as an array.

Returns:

  • (array)

    arguments



138
139
140
# File 'lib/navvy/job.rb', line 138

def args
  arguments.is_a?(Array) ? arguments : YAML.load(arguments)
end

#completed(return_value = nil) ⇒ true, false

Mark the job as completed. Will set completed_at to the current time and optionally add the return value if provided.

update_attributes call

Parameters:

  • return_value (String) (defaults to: nil)

    the return value you want to store.

Returns:

  • (true, false)

    update_attributes the result of the



102
103
104
105
106
107
# File 'lib/navvy/job/sequel.rb', line 102

def completed(return_value = nil)
  update({
    :completed_at =>  Time.now,
    :return =>        return_value
  })
end

#completed_at?true, false Also known as: completed?

Check if completed_at is set.

Returns:

  • (true, false)

    set?



120
121
122
# File 'lib/navvy/job.rb', line 120

def completed_at?
  !completed_at.nil?
end

#durationTime, Integer

Check how long it took for a job to complete or fail.

Returns:

  • (Time, Integer)

    time the time it took.



111
112
113
# File 'lib/navvy/job.rb', line 111

def duration
  ran? ? (completed_at || failed_at) - started_at : 0
end

#failed(message = nil) ⇒ true, false

Mark the job as failed. Will set failed_at to the current time and optionally add the exception message if provided. Also, it will retry the job unless max_attempts has been reached.

update_attributes call

Parameters:

  • exception (String)

    the exception message you want to store.

Returns:

  • (true, false)

    update_attributes the result of the



119
120
121
122
123
124
125
# File 'lib/navvy/job/sequel.rb', line 119

def failed(message = nil)
  self.retry unless times_failed >= self.class.max_attempts
  update(
    :failed_at => Time.now,
    :exception => message
  )
end

#failed_at?true, false Also known as: failed?

Check if failed_at is set.

Returns:

  • (true, false)

    set?



129
130
131
# File 'lib/navvy/job.rb', line 129

def failed_at?
  !failed_at.nil?
end

#ran?true, false

Check if the job has been run.

Returns:

  • (true, false)

    ran



102
103
104
# File 'lib/navvy/job.rb', line 102

def ran?
  completed? || failed?
end

#retryNavvy::Job

Retry the current job. Will add self to the queue again, giving the clone a parend_id equal to self.id. Also, the priority of the new job will be the same as its parent’s and it’ll set the :run_at date to N ** 4, where N is the times_failed count.

Returns:



83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/navvy/job.rb', line 83

def retry
  self.class.enqueue(
    object,
    method_name,
    *(args << {
      :job_options => {
        :parent_id => parent_id || id,
        :run_at => Time.now + times_failed ** 4,
        :priority => priority
      }
    })
  )
end

#runString

Run the job. Will delete the Navvy::Job record and return its return value if it runs successfully unless Navvy::Job.keep is set. If a job fails, it’ll call Navvy::Job#failed and pass the exception message. Failed jobs will not get deleted.

Examples:

job = Navvy::Job.next # finds the next available job in the queue
job.run               # runs the job and returns the job's return value

Returns:

  • (String)

    return value or exception message of the called method.



64
65
66
67
68
69
70
71
72
73
# File 'lib/navvy/job.rb', line 64

def run
  begin
    started
    result = constantize(object).send(method_name, *args)
    Navvy::Job.keep? ? completed : destroy
    result
  rescue Exception => exception
    failed(exception.message)
  end
end

#startedtrue, false

Mark the job as started. Will set started_at to the current time.

update_attributes call

Returns:

  • (true, false)

    update_attributes the result of the



87
88
89
90
91
# File 'lib/navvy/job/sequel.rb', line 87

def started
  update({
    :started_at =>  Time.now
  })
end

#status:pending, ...

Get the job status

Returns:

  • (:pending, :completed, :failed)

    status



147
148
149
150
151
# File 'lib/navvy/job.rb', line 147

def status
  return :completed if completed?
  return :failed if failed?
  :pending
end

#times_failedInteger

Check how many times the job has failed. Will try to find jobs with a parent_id that’s the same as self.id and count them

Returns:

  • (Integer)

    count the amount of times the job has failed



133
134
135
136
137
138
# File 'lib/navvy/job/sequel.rb', line 133

def times_failed
  i = parent_id || id
  self.class.filter(
    ({:id => i} | {:parent_id => i}), ~{:failed_at => nil}
  ).count
end