Class: SimpleScheduler::Task
- Inherits:
-
Object
- Object
- SimpleScheduler::Task
- Defined in:
- lib/simple_scheduler/task.rb
Overview
Class for parsing each task in the scheduler config YAML file and returning the values needed to schedule the task in the future.
Constant Summary collapse
- DEFAULT_QUEUE_AHEAD_MINUTES =
360
Instance Attribute Summary collapse
-
#job_class ⇒ Class
readonly
The class of the job or worker.
-
#params ⇒ Hash
readonly
The params used to create the task.
Class Method Summary collapse
-
.scheduled_set ⇒ Sidekiq::ScheduledSet
Loads the scheduled jobs from Sidekiq once to avoid loading from Redis for each task when looking up existing scheduled jobs.
Instance Method Summary collapse
-
#at ⇒ SimpleScheduler::At
The task’s first run time as a Time-like object.
-
#existing_jobs ⇒ Array<Sidekiq::SortedEntry>
Returns an array of existing jobs matching the job class of the task.
-
#existing_run_times ⇒ Array<Time>
Returns an array of existing future run times that have already been scheduled.
-
#expires_after ⇒ String
The time between the scheduled and actual run time that should cause the job not to run.
-
#frequency ⇒ ActiveSupport::Duration
How often the job will be run.
-
#future_run_times ⇒ Array<Time>
Returns an array Time objects for future run times based on the current time and the given minutes to look ahead.
-
#initialize(params) ⇒ Task
constructor
Initializes a task by parsing the params so the task can be queued in the future.
-
#job_class_name ⇒ String
The class name of the job or worker.
-
#name ⇒ String
The name of the task as defined in the YAML config.
-
#queue_ahead ⇒ Integer
The number of minutes that jobs should be queued in the future.
-
#time_zone ⇒ ActiveSupport::TimeZone
The time zone to use when parsing the ‘at` option.
Constructor Details
#initialize(params) ⇒ Task
Initializes a task by parsing the params so the task can be queued in the future.
23 24 25 26 |
# File 'lib/simple_scheduler/task.rb', line 23 def initialize(params) validate_params!(params) @params = params end |
Instance Attribute Details
#job_class ⇒ Class (readonly)
Returns The class of the job or worker.
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 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 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 |
# File 'lib/simple_scheduler/task.rb', line 9 class Task attr_reader :job_class, :params DEFAULT_QUEUE_AHEAD_MINUTES = 360 # 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 time between the scheduled and actual run time that should cause the job not 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 def initialize(params) validate_params!(params) @params = params end # The task's first run time as a Time-like object. # @return [SimpleScheduler::At] def at @at ||= At.new(@params[:at], time_zone) end # The time between the scheduled and actual run time that should cause the job not to run. # @return [String] def expires_after @params[:expires_after] end # Returns an array of existing jobs matching the job class of the task. # @return [Array<Sidekiq::SortedEntry>] 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>] def existing_run_times @existing_run_times ||= existing_jobs.map(&:at) end # How often the job will be run. # @return [ActiveSupport::Duration] 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>] 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] def job_class_name @params[:class] end # The name of the task as defined in the YAML config. # @return [String] def name @params[:name] end # The number of minutes that jobs should be queued in the future. # @return [Integer] 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] def time_zone @time_zone ||= params[:tz] ? ActiveSupport::TimeZone.new(params[:tz]) : Time.zone 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] def self.scheduled_set @scheduled_set ||= Sidekiq::ScheduledSet.new end private def minutes_queued_ahead(last_run_time) (last_run_time - Time.now) / 1.minute end 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 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 end |
#params ⇒ Hash (readonly)
Returns The params used to create the task.
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 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 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 |
# File 'lib/simple_scheduler/task.rb', line 9 class Task attr_reader :job_class, :params DEFAULT_QUEUE_AHEAD_MINUTES = 360 # 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 time between the scheduled and actual run time that should cause the job not 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 def initialize(params) validate_params!(params) @params = params end # The task's first run time as a Time-like object. # @return [SimpleScheduler::At] def at @at ||= At.new(@params[:at], time_zone) end # The time between the scheduled and actual run time that should cause the job not to run. # @return [String] def expires_after @params[:expires_after] end # Returns an array of existing jobs matching the job class of the task. # @return [Array<Sidekiq::SortedEntry>] 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>] def existing_run_times @existing_run_times ||= existing_jobs.map(&:at) end # How often the job will be run. # @return [ActiveSupport::Duration] 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>] 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] def job_class_name @params[:class] end # The name of the task as defined in the YAML config. # @return [String] def name @params[:name] end # The number of minutes that jobs should be queued in the future. # @return [Integer] 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] def time_zone @time_zone ||= params[:tz] ? ActiveSupport::TimeZone.new(params[:tz]) : Time.zone 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] def self.scheduled_set @scheduled_set ||= Sidekiq::ScheduledSet.new end private def minutes_queued_ahead(last_run_time) (last_run_time - Time.now) / 1.minute end 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 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 end |
Class Method Details
.scheduled_set ⇒ Sidekiq::ScheduledSet
Loads the scheduled jobs from Sidekiq once to avoid loading from Redis for each task when looking up existing scheduled jobs.
109 110 111 |
# File 'lib/simple_scheduler/task.rb', line 109 def self.scheduled_set @scheduled_set ||= Sidekiq::ScheduledSet.new end |
Instance Method Details
#at ⇒ SimpleScheduler::At
The task’s first run time as a Time-like object.
30 31 32 |
# File 'lib/simple_scheduler/task.rb', line 30 def at @at ||= At.new(@params[:at], time_zone) end |
#existing_jobs ⇒ Array<Sidekiq::SortedEntry>
Returns an array of existing jobs matching the job class of the task.
42 43 44 45 46 47 48 |
# 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 |
#existing_run_times ⇒ Array<Time>
Returns an array of existing future run times that have already been scheduled.
52 53 54 |
# File 'lib/simple_scheduler/task.rb', line 52 def existing_run_times @existing_run_times ||= existing_jobs.map(&:at) end |
#expires_after ⇒ String
The time between the scheduled and actual run time that should cause the job not to run.
36 37 38 |
# File 'lib/simple_scheduler/task.rb', line 36 def expires_after @params[:expires_after] end |
#frequency ⇒ ActiveSupport::Duration
How often the job will be run.
58 59 60 |
# File 'lib/simple_scheduler/task.rb', line 58 def frequency @frequency ||= parse_frequency(@params[:every]) end |
#future_run_times ⇒ Array<Time>
Returns an array Time objects for future run times based on the current time and the given minutes to look ahead.
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
# File 'lib/simple_scheduler/task.rb', line 65 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 |
#job_class_name ⇒ String
The class name of the job or worker.
84 85 86 |
# File 'lib/simple_scheduler/task.rb', line 84 def job_class_name @params[:class] end |
#name ⇒ String
The name of the task as defined in the YAML config.
90 91 92 |
# File 'lib/simple_scheduler/task.rb', line 90 def name @params[:name] end |
#queue_ahead ⇒ Integer
The number of minutes that jobs should be queued in the future.
96 97 98 |
# File 'lib/simple_scheduler/task.rb', line 96 def queue_ahead @queue_ahead ||= @params[:queue_ahead] || DEFAULT_QUEUE_AHEAD_MINUTES end |
#time_zone ⇒ ActiveSupport::TimeZone
The time zone to use when parsing the ‘at` option.
102 103 104 |
# File 'lib/simple_scheduler/task.rb', line 102 def time_zone @time_zone ||= params[:tz] ? ActiveSupport::TimeZone.new(params[:tz]) : Time.zone end |