class RecurringJob
Copyright (C) 2015 OL2, Inc. See LICENSE.txt for details.
Class declaration in recurring_job/class_decl gives the parent class, which is a new Struct().
Constants
- VERSION
Public Class Methods
all()
click to toggle source
# File lib/recurring_job/recurring_job.rb, line 160 def self.all # Return all jobs with named queues (may get extra jobs if other jobs use named queues) Delayed::Job.all.where.not(queue:nil) end
default_interval()
click to toggle source
# File lib/recurring_job/recurring_job.rb, line 93 def self.default_interval 1.day end
default_queue()
click to toggle source
# File lib/recurring_job/recurring_job.rb, line 97 def self.default_queue self.name end
get_option(job, option)
click to toggle source
# File lib/recurring_job/recurring_job.rb, line 139 def self.get_option(job, option) # given a job from the queue, # parse the handler yaml and return options[option] y = YAML.load(job.handler) y.options && y.options[option] end
in_queue_or_running?(queue)
click to toggle source
# File lib/recurring_job/recurring_job.rb, line 84 def self.in_queue_or_running?(queue) # is this job currently in progress? # will return false if the job is already done # (the job is out of the queue when it's done.) queue ||= default_queue job = Delayed::Job.find_by(queue:queue) job end
job_id_running?(job_id)
click to toggle source
# File lib/recurring_job/recurring_job.rb, line 122 def self.job_id_running?(job_id) # is a job with the given id running? job = Delayed::Job.find_by(id:job_id) # don't use find, don't want to raise an error if not found #logger.debug("Is job #{job_id} running? #{job.inspect}") job && job.locked_by end
job_interval(job)
click to toggle source
# File lib/recurring_job/recurring_job.rb, line 146 def self.job_interval(job) # given a job from the queue # parse the handler yaml and give back the current interval # nil means no interval set get_option(job, :interval) end
list_job_intervals()
click to toggle source
# File lib/recurring_job/recurring_job.rb, line 165 def self.list_job_intervals # lists all jobs that have a queue associated with them and intervals (if any) # {queue_name => {interval:interval, next_run:<run_at>}} job_list = {} self.all.each do |job| queue = job.queue next unless queue job_list[queue] = {interval:self.job_interval(job), next_run:job.run_at} end job_list end
logger()
click to toggle source
# File lib/recurring_job/recurring_job.rb, line 16 def self.logger @@logger ||= Logger.new(STDOUT) @@logger end
logger=(new_logger)
click to toggle source
(parts inspired by gist.github.com/JoshMcKin/1648242)
# File lib/recurring_job/recurring_job.rb, line 12 def self.logger=(new_logger) @@logger = new_logger end
next_scheduled_job(this_job=nil, queue_name = nil)
click to toggle source
# File lib/recurring_job/recurring_job.rb, line 101 def self.next_scheduled_job(this_job=nil, queue_name = nil) # return job if it exists queue_name ||= default_queue conditions = ['queue = ? AND failed_at IS NULL', queue_name] unless this_job.blank? conditions[0] << " AND id != ?" conditions << this_job.id end Delayed::Job.where(conditions).first end
queue_once(options = {})
click to toggle source
# File lib/recurring_job/recurring_job.rb, line 75 def self.queue_once(options = {}) # just run this to add the queue to run one time only (not scheduled) # IMPORTANT: don't put in same queue name as recurring job and DON'T specify an interval in the options! # Can use the queue field, but do not use the job name! queue = options[:queue] raise "Can't run Recurring Job once in queue: #{default_queue}" if queue == default_queue Delayed::Job.enqueue(self.new(options), :queue => queue) end
running?(queue=nil)
click to toggle source
# File lib/recurring_job/recurring_job.rb, line 115 def self.running?(queue=nil) # is this job currently running? queue ||= default_queue job = Delayed::Job.find_by(queue:queue) job && job.locked_by end
schedule_job(options = {}, this_job=nil)
click to toggle source
# File lib/recurring_job/recurring_job.rb, line 25 def self.schedule_job(options = {}, this_job=nil) # schedule this job (if you just want job to run once, just use queue_once ) # this_job is currently running instance (if any)(so we can check against it) # options - # :interval => number of seconds between job runs (from end of one to beginning of next) # default, once a day # :queue => name of queue to use # default: the name of this class # only one job will be scheduled at a time for any given queue # :first_start_time => specify a specific time for this run, then use interval after that # Plus any other options (if any) you want sent through to the underlying job. options ||= {} # in case sent in explicitly as nil options[:interval] ||= default_interval options[:queue] ||= default_queue queue_name = options[:queue] other_job = next_scheduled_job(this_job, queue_name) if other_job logger.info "#{queue_name} job is already scheduled for #{other_job.run_at}." # Still set any new start time or interval options for next time. if job_interval(other_job) != options[:interval].to_i logger.info " Updating interval to #{options[:interval]}" set_job_interval(other_job, options[:interval]) end if options[:first_start_time] && options[:first_start_time] != other_job.run_at logger.info " Updating start time to #{options[:first_start_time]}" other_job.run_at = options[:first_start_time] other_job.save end else # if start time is specified, use it ONLY this time (to start), don't pass on in options run_time = options.delete(:first_start_time) run_time ||= Time.now + options[:interval].to_i # make sure it's an integer (e.g. if sent in as 1.day) other_job = Delayed::Job.enqueue self.new(options), :run_at => run_time, :queue=> queue_name logger.info "The next #{queue_name} job has been scheduled for #{other_job.run_at}." end other_job end
set_job_interval(job, interval)
click to toggle source
# File lib/recurring_job/recurring_job.rb, line 153 def self.set_job_interval(job, interval) # given a job from the queue # parse the handler yaml and set the job interval interval ||= default_interval set_option(job, :interval, interval.to_i) end
set_option(job, option, value)
click to toggle source
# File lib/recurring_job/recurring_job.rb, line 129 def self.set_option(job, option, value) # given a job from the queue, # parse the handler yaml and set options[option] to value y = YAML.load(job.handler) y.options ||= {} y.options[option] = value job.handler = y.to_yaml job.save! end
unschedule_job()
click to toggle source
# File lib/recurring_job/recurring_job.rb, line 66 def self.unschedule_job # shortcut for deleting the job from Delayed Job # returns true if there was a job to delete, false otherwise recurring_job = self.next_scheduled_job recurring_job.destroy if recurring_job return recurring_job # true if there was a job to unschedule end
Public Instance Methods
after(job)
click to toggle source
# File lib/recurring_job/recurring_job.rb, line 191 def after(job) # Remember to call super if you implement this hook in your own job! # Reschedule this job when we're done. Whether there's an error in this run # or not, we always want to reschedule if an interval was specified if options[:interval] # if an interval was specified, make sure there's a future job using the same options as before. # Otherwise, this is a one time run so don't reschedule. options.delete(:delayed_job_id) # don't pass on the previous delayed job id # logger.debug("Scheduling again: #{options.inspect}") self.class.schedule_job(options, job) end end
before(job)
click to toggle source
# File lib/recurring_job/recurring_job.rb, line 183 def before(job) # Remember to call super if you implement this hook in your own job! # Send in the job_id so that the RecurringJob can use it if it needs it. # (during perform we otherwise don't have access to "job") options[:delayed_job_id] = job.id.to_s end
enqueue(job)
click to toggle source
# File lib/recurring_job/recurring_job.rb, line 217 def enqueue(job) # Remember to call super if you implement this hook in your own job! end
error(job, exception)
click to toggle source
# File lib/recurring_job/recurring_job.rb, line 209 def error(job, exception) # Remember to call super if you implement this hook in your own job! end
failure(job)
click to toggle source
# File lib/recurring_job/recurring_job.rb, line 213 def failure(job) # Remember to call super if you implement this hook in your own job! end
logger()
click to toggle source
# File lib/recurring_job/recurring_job.rb, line 21 def logger RecurringJob.logger end
perform()
click to toggle source
# File lib/recurring_job/recurring_job.rb, line 177 def perform # should be overridden by real job to do the actual work! # (don't call super for this...) raise "Must override perform in #{self.class.name}" end
success(job)
click to toggle source
# File lib/recurring_job/recurring_job.rb, line 205 def success(job) # Remember to call super if you implement this hook in your own job! end