class GoodJob::CronManager

CronManagers enqueue jobs on a repeating schedule.

Attributes

schedules[R]

Job configuration to be scheduled @return [Hash]

Public Class Methods

new(schedules = {}, start_on_initialize: false) click to toggle source

@param schedules [Hash] @param start_on_initialize [Boolean]

   # File lib/good_job/cron_manager.rb
33 def initialize(schedules = {}, start_on_initialize: false)
34   @running = false
35   @schedules = schedules
36   @tasks = Concurrent::Hash.new
37 
38   self.class.instances << self
39 
40   start if start_on_initialize
41 end
task_observer(time, output, thread_error) click to toggle source

Task observer for cron task @param time [Time] @param output [Object] @param thread_error [Exception]

   # File lib/good_job/cron_manager.rb
21 def self.task_observer(time, output, thread_error) # rubocop:disable Lint/UnusedMethodArgument
22   return if thread_error.is_a? Concurrent::CancelledOperationError
23 
24   GoodJob.on_thread_error.call(thread_error) if thread_error && GoodJob.on_thread_error.respond_to?(:call)
25 end

Public Instance Methods

create_task(cron_key) click to toggle source

Enqueues a scheduled task @param cron_key [Symbol, String] the key within the schedule to use

    # File lib/good_job/cron_manager.rb
 82 def create_task(cron_key)
 83   schedule = @schedules[cron_key]
 84   return false if schedule.blank?
 85 
 86   fugit = Fugit::Cron.parse(schedule.fetch(:cron))
 87   delay = [(fugit.next_time - Time.current).to_f, 0].max
 88 
 89   future = Concurrent::ScheduledTask.new(delay, args: [self, cron_key]) do |thr_scheduler, thr_cron_key|
 90     # Re-schedule the next cron task before executing the current task
 91     thr_scheduler.create_task(thr_cron_key)
 92 
 93     CurrentExecution.reset
 94     CurrentExecution.cron_key = thr_cron_key
 95 
 96     Rails.application.executor.wrap do
 97       schedule = thr_scheduler.schedules.fetch(thr_cron_key).with_indifferent_access
 98       job_class = schedule.fetch(:class).constantize
 99 
100       job_set_value = schedule.fetch(:set, {})
101       job_set = job_set_value.respond_to?(:call) ? job_set_value.call : job_set_value
102 
103       job_args_value = schedule.fetch(:args, [])
104       job_args = job_args_value.respond_to?(:call) ? job_args_value.call : job_args_value
105 
106       job_class.set(job_set).perform_later(*job_args)
107     end
108   end
109 
110   @tasks[cron_key] = future
111   future.add_observer(self.class, :task_observer)
112   future.execute
113 end
restart(timeout: nil) click to toggle source

Stop and restart @param timeout [Numeric, nil] Unused but retained for compatibility

   # File lib/good_job/cron_manager.rb
63 def restart(timeout: nil) # rubocop:disable Lint/UnusedMethodArgument
64   shutdown
65   start
66 end
running?() click to toggle source

Tests whether the manager is running. @return [Boolean, nil]

   # File lib/good_job/cron_manager.rb
70 def running?
71   @running
72 end
shutdown(timeout: nil) click to toggle source

Stop/cancel any scheduled tasks @param timeout [Numeric, nil] Unused but retained for compatibility

   # File lib/good_job/cron_manager.rb
53 def shutdown(timeout: nil) # rubocop:disable Lint/UnusedMethodArgument
54   @running = false
55   @tasks.each do |_cron_key, task|
56     task.cancel
57   end
58   @tasks.clear
59 end
shutdown?() click to toggle source

Tests whether the manager is shutdown. @return [Boolean, nil]

   # File lib/good_job/cron_manager.rb
76 def shutdown?
77   !running?
78 end
start() click to toggle source

Schedule tasks that will enqueue jobs based on their schedule

   # File lib/good_job/cron_manager.rb
44 def start
45   ActiveSupport::Notifications.instrument("cron_manager_start.good_job", cron_jobs: @schedules) do
46     @running = true
47     schedules.each_key { |cron_key| create_task(cron_key) }
48   end
49 end