Skip to content
This repository has been archived by the owner on Apr 11, 2023. It is now read-only.

Commit

Permalink
merged with development
Browse files Browse the repository at this point in the history
  • Loading branch information
Jeff Kreeftmeijer committed Jan 30, 2010
2 parents 0adbf3a + 76fb072 commit 30b8c36
Show file tree
Hide file tree
Showing 15 changed files with 553 additions and 408 deletions.
3 changes: 2 additions & 1 deletion generators/navvy/templates/migration.rb
Expand Up @@ -7,14 +7,15 @@ def self.up
t.integer :priority, :default => 0
t.string :return
t.string :exception
t.integer :parent_id
t.datetime :created_at
t.datetime :run_at
t.datetime :started_at
t.datetime :completed_at
t.datetime :failed_at
end
end

def self.down
drop_table :jobs
end
Expand Down
16 changes: 16 additions & 0 deletions lib/navvy.rb
@@ -1,3 +1,19 @@
require File.expand_path(File.dirname(__FILE__) + '/navvy/job')
require File.expand_path(File.dirname(__FILE__) + '/navvy/worker')
require File.expand_path(File.dirname(__FILE__) + '/navvy/log')
require File.expand_path(File.dirname(__FILE__) + '/navvy/configuration')
require File.expand_path(File.dirname(__FILE__) + '/navvy/monitor')

module Navvy
class << self
attr_writer :configuration
end

def self.configuration
@configuration ||= Configuration.new
end

def self.configure
yield(self.configuration)
end
end
15 changes: 15 additions & 0 deletions lib/navvy/configuration.rb
@@ -0,0 +1,15 @@
module Navvy
class Configuration
attr_accessor :job_limit, :keep_jobs, :logger, :quiet, :sleep_time,
:max_attempts

def initialize
@job_limit = 100
@keep_jobs = false
@logger = nil
@quiet = false
@sleep_time = 5
@max_attempts = 25
end
end
end
148 changes: 148 additions & 0 deletions lib/navvy/job.rb
@@ -0,0 +1,148 @@
module Navvy
class Job
class << self
attr_writer :limit, :keep, :max_attempts
end

##
# Default limit of jobs to be fetched.
#
# @return [Integer] limit

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

##
# If and how long the jobs should be kept.
#
# @return [Fixnum, true, false] keep

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

##
# How often should a job be retried?
#
# @return [Fixnum] max_attempts

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

##
# Should the job be kept?
#
# @return [true, false] keep

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

##
# 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 update the Navvy::Job record to include the exception
# message it sent back and set the :failed_at date. Failed jobs never get
# deleted.
#
# @example
# job = Navvy::Job.next # finds the next available job in the queue
# job.run # runs the job and returns the job's return value
#
# @return [String] return value of the called method.

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

##
# Retry the current job. Will add self to the queue again, giving the clone
# a parend_id equal to self.id.
#
# @return [true, false]

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

##
# Check if the job has been run.
#
# @return [true, false] ran

def ran?
completed? || failed?
end

##
# Check how long it took for a job to complete or fail
#
# @return [Time, Integer] time the time it took

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

##
# Check if completed_at is set
#
# @return [true, false] set?

def completed_at?
!completed_at.nil?
end

##
# Check if failed_at is set
#
# @return [true, false] set?

def failed_at?
!failed_at.nil?
end

##
# Get the job arguments as an array
#
# @return [array] arguments

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

##
# Get the job status
#
# @return [:pending, :completed, :failed] status

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

alias_method :completed?, :completed_at?
alias_method :failed?, :failed_at?
end
end
128 changes: 23 additions & 105 deletions lib/navvy/job/active_record.rb
Expand Up @@ -3,30 +3,6 @@

module Navvy
class Job < ActiveRecord::Base
class << self
attr_writer :limit
attr_accessor :keep
end

##
# Default limit of jobs to be fetched
#
# @return [Integer] limit

def self.limit
@limit || 100
end

##
# Should the job be kept?
#
# @return [true, false] keep

def self.keep?
keep = (@keep || false)
return keep.from_now >= Time.now if keep.is_a? Fixnum
keep
end

##
# Add a job to the job queue.
Expand All @@ -41,13 +17,15 @@ 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

create(
:object => object.to_s,
:method_name => method_name.to_s,
:arguments => args,
:priority => options[:priority] || 0,
:parent_id => options[:parent_id],
:run_at => options[:run_at] || Time.now,
:created_at => Time.now
)
Expand Down Expand Up @@ -96,31 +74,15 @@ def self.cleanup
end

##
# 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 update the Navvy::Job record to include the exception
# message it sent back and set the :failed_at date. Failed jobs never get
# deleted.
#
# @example
# job = Navvy::Job.next # finds the next available job in the queue
# job.run # runs the job and returns the job's return value
# Mark the job as started. Will set started_at to the current time.
#
# @return [String] return value of the called method.

def run
begin
update_attributes(:started_at => Time.now)
if args.empty?
result = object.constantize.send(method_name)
else
result = object.constantize.send(method_name, *args)
end
Navvy::Job.keep? ? completed : destroy
result
rescue Exception => exception
failed(exception.message)
end
# @return [true, false] update_attributes the result of the
# update_attributes call

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

##
Expand All @@ -141,77 +103,33 @@ def completed(return_value = nil)

##
# Mark the job as failed. Will set failed_at to the current time and
# optionally add the exception message if provided.
# optionally add the exception message if provided. Also, it will retry
# the job unless max_attempts has been reached.
#
# @param [String] exception the exception message you want to store.
#
# @return [true, false] update_attributes the result of the
# update_attributes call

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

##
# Check if the job has been run.
#
# @return [true, false] ran

def ran?
completed? || failed?
end

##
# Check how long it took for a job to complete or fail
#
# @return [Time, Integer] time the time it took

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

##
# Check if completed_at is set
#
# @return [true, false] set?

def completed_at?
!completed_at.nil?
end

##
# Check if failed_at is set
#
# @return [true, false] set?

def failed_at?
!failed_at.nil?
end

##
# Get the job arguments as an array
#
# @return [array] arguments

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

##
# Get the job status
# 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
#
# @return [:pending, :completed, :failed] status
# @return [Integer] count the amount of times the job has failed

def status
return :completed if completed?
return :failed if failed?
:pending
def times_failed
i = parent_id || id
self.class.count(
:conditions => "`id` == '#{i}' OR `parent_id` == '#{i}'"
)
end

alias_method :completed?, :completed_at?
alias_method :failed?, :failed_at?
end
end

0 comments on commit 30b8c36

Please sign in to comment.