class SimpleScheduler::Task
Class for parsing each task in the scheduler config YAML file and returning the values needed to schedule the task in the future.
@!attribute [r] job_class
@return [Class] The class of the job or worker.
@!attribute [r] params
@return [Hash] The params used to create the task
Constants
- DEFAULT_QUEUE_AHEAD_MINUTES
Attributes
Public Class Methods
Initializes a task by parsing the params so the task can be queued in the future. @param params [Hash] @option params [String] :class The class of the Active Job or Sidekiq Worker @option params [String] :every How frequently the job will be performed @option params [String] :at The starting time for the interval @option params [String] :expires_after The interval used to determine how late the job is allowed to run @option params [Integer] :queue_ahead The number of minutes that jobs should be queued in the future @option params [String] :task_name The name of the task as defined in the YAML config @option params [String] :tz The time zone to use when parsing the `at` option
# File lib/simple_scheduler/task.rb, line 23 def initialize(params) validate_params!(params) @params = params end
Loads the scheduled jobs from Sidekiq once to avoid loading from Redis for each task when looking up existing scheduled jobs. @return [Sidekiq::ScheduledSet]
# File lib/simple_scheduler/task.rb, line 112 def self.scheduled_set @scheduled_set ||= Sidekiq::ScheduledSet.new end
Public Instance Methods
The task's first run time as a Time-like object. @return [SimpleScheduler::At]
# File lib/simple_scheduler/task.rb, line 30 def at @at ||= At.new(@params[:at], time_zone) end
Returns an array of existing jobs matching the job class of the task. @return [Array<Sidekiq::SortedEntry>]
# File lib/simple_scheduler/task.rb, line 42 def existing_jobs @existing_jobs ||= SimpleScheduler::Task.scheduled_set.select do |job| next unless job.display_class == "SimpleScheduler::FutureJob" task_params = job.display_args[0].symbolize_keys task_params[:class] == job_class_name && task_params[:name] == name end.to_a end
Returns an array of existing future run times that have already been scheduled. @return [Array<Time>]
# File lib/simple_scheduler/task.rb, line 53 def existing_run_times @existing_run_times ||= existing_jobs.map(&:at) end
The time between the scheduled and actual run time that should cause the job not to run. @return [String]
# File lib/simple_scheduler/task.rb, line 36 def expires_after @params[:expires_after] end
How often the job will be run. @return [ActiveSupport::Duration]
# File lib/simple_scheduler/task.rb, line 59 def frequency @frequency ||= parse_frequency(@params[:every]) end
Returns an array Time objects for future run times based on the current time and the given minutes to look ahead. @return [Array<Time>] rubocop:disable Metrics/AbcSize
# File lib/simple_scheduler/task.rb, line 67 def future_run_times future_run_times = existing_run_times.dup last_run_time = future_run_times.last || at - frequency last_run_time = last_run_time.in_time_zone(time_zone) # Ensure there are at least two future jobs scheduled and that the queue ahead time is filled while future_run_times.length < 2 || minutes_queued_ahead(last_run_time) < queue_ahead last_run_time = frequency.from_now(last_run_time) # The hour may not match because of a shift caused by DST in previous run times, # so we need to ensure that the hour matches the specified hour if given. last_run_time = last_run_time.change(hour: at.hour, min: at.min) if at.hour? future_run_times << last_run_time end future_run_times end
The class name of the job or worker. @return [String]
# File lib/simple_scheduler/task.rb, line 87 def job_class_name @params[:class] end
The name of the task as defined in the YAML config. @return [String]
# File lib/simple_scheduler/task.rb, line 93 def name @params[:name] end
The number of minutes that jobs should be queued in the future. @return [Integer]
# File lib/simple_scheduler/task.rb, line 99 def queue_ahead @queue_ahead ||= @params[:queue_ahead] || DEFAULT_QUEUE_AHEAD_MINUTES end
The time zone to use when parsing the `at` option. @return [ActiveSupport::TimeZone]
# File lib/simple_scheduler/task.rb, line 105 def time_zone @time_zone ||= params[:tz] ? ActiveSupport::TimeZone.new(params[:tz]) : Time.zone end
Private Instance Methods
# File lib/simple_scheduler/task.rb, line 118 def minutes_queued_ahead(last_run_time) (last_run_time - Time.now) / 60 end
# File lib/simple_scheduler/task.rb, line 122 def parse_frequency(every_string) split_duration = every_string.split(".") frequency = split_duration[0].to_i frequency_units = split_duration[1] frequency.send(frequency_units) end
# File lib/simple_scheduler/task.rb, line 129 def validate_params!(params) raise ArgumentError, "Missing param `class` specifying the class of the job to run." unless params.key?(:class) raise ArgumentError, "Missing param `every` specifying how often the job should run." unless params.key?(:every) @job_class = params[:class].constantize params[:name] ||= params[:class] end