dynamodb-sidekiq-scheduler 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
 - data/CHANGELOG.md +69 -0
 - data/MIT-LICENSE +20 -0
 - data/README.md +521 -0
 - data/Rakefile +29 -0
 - data/lib/sidekiq/scheduler.rb +3 -0
 - data/lib/sidekiq-scheduler/config.rb +80 -0
 - data/lib/sidekiq-scheduler/extensions/schedule.rb +4 -0
 - data/lib/sidekiq-scheduler/extensions/web.rb +14 -0
 - data/lib/sidekiq-scheduler/job_presenter.rb +74 -0
 - data/lib/sidekiq-scheduler/manager.rb +44 -0
 - data/lib/sidekiq-scheduler/redis_manager.rb +241 -0
 - data/lib/sidekiq-scheduler/rufus_utils.rb +29 -0
 - data/lib/sidekiq-scheduler/schedule.rb +154 -0
 - data/lib/sidekiq-scheduler/scheduler.rb +356 -0
 - data/lib/sidekiq-scheduler/sidekiq_adapter.rb +80 -0
 - data/lib/sidekiq-scheduler/utils.rb +143 -0
 - data/lib/sidekiq-scheduler/version.rb +3 -0
 - data/lib/sidekiq-scheduler/web.rb +98 -0
 - data/lib/sidekiq-scheduler.rb +28 -0
 - data/web/assets/stylesheets-scheduler/recurring_jobs.css +42 -0
 - data/web/locales/cs.yml +14 -0
 - data/web/locales/de.yml +16 -0
 - data/web/locales/en.yml +23 -0
 - data/web/locales/es.yml +14 -0
 - data/web/locales/fr.yml +13 -0
 - data/web/locales/it.yml +14 -0
 - data/web/locales/ja.yml +14 -0
 - data/web/locales/nl.yml +14 -0
 - data/web/locales/pl.yml +14 -0
 - data/web/locales/pt-BR.yml +19 -0
 - data/web/locales/ru.yml +16 -0
 - data/web/locales/sv.yml +14 -0
 - data/web/locales/zh-cn.yml +14 -0
 - data/web/views/recurring_job.erb +17 -0
 - data/web/views/recurring_jobs.erb +113 -0
 - metadata +257 -0
 
| 
         @@ -0,0 +1,80 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module SidekiqScheduler
         
     | 
| 
      
 2 
     | 
    
         
            +
              class Config
         
     | 
| 
      
 3 
     | 
    
         
            +
                # We have to set the default as nil because the scheduler could be instantiated without
         
     | 
| 
      
 4 
     | 
    
         
            +
                # passing the sidekiq config, and in those scenarios we don't want to fail
         
     | 
| 
      
 5 
     | 
    
         
            +
                def initialize(sidekiq_config: nil, without_defaults: false)
         
     | 
| 
      
 6 
     | 
    
         
            +
                  @sidekiq_config = sidekiq_config
         
     | 
| 
      
 7 
     | 
    
         
            +
                  @scheduler_config = fetch_scheduler_config(sidekiq_config, without_defaults)
         
     | 
| 
      
 8 
     | 
    
         
            +
                end
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                def enabled?
         
     | 
| 
      
 11 
     | 
    
         
            +
                  scheduler_config[:enabled]
         
     | 
| 
      
 12 
     | 
    
         
            +
                end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                def enabled=(value)
         
     | 
| 
      
 15 
     | 
    
         
            +
                  scheduler_config[:enabled] = value
         
     | 
| 
      
 16 
     | 
    
         
            +
                end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                def dynamic?
         
     | 
| 
      
 19 
     | 
    
         
            +
                  scheduler_config[:dynamic]
         
     | 
| 
      
 20 
     | 
    
         
            +
                end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                def dynamic=(value)
         
     | 
| 
      
 23 
     | 
    
         
            +
                  scheduler_config[:dynamic] = value
         
     | 
| 
      
 24 
     | 
    
         
            +
                end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                def dynamic_every?
         
     | 
| 
      
 27 
     | 
    
         
            +
                  scheduler_config[:dynamic_every]
         
     | 
| 
      
 28 
     | 
    
         
            +
                end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                def dynamic_every=(value)
         
     | 
| 
      
 31 
     | 
    
         
            +
                  scheduler_config[:dynamic_every] = value
         
     | 
| 
      
 32 
     | 
    
         
            +
                end
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                def schedule
         
     | 
| 
      
 35 
     | 
    
         
            +
                  scheduler_config[:schedule]
         
     | 
| 
      
 36 
     | 
    
         
            +
                end
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
                def schedule=(value)
         
     | 
| 
      
 39 
     | 
    
         
            +
                  scheduler_config[:schedule] = value
         
     | 
| 
      
 40 
     | 
    
         
            +
                end
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
                def listened_queues_only?
         
     | 
| 
      
 43 
     | 
    
         
            +
                  scheduler_config[:listened_queues_only]
         
     | 
| 
      
 44 
     | 
    
         
            +
                end
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
                def listened_queues_only=(value)
         
     | 
| 
      
 47 
     | 
    
         
            +
                  scheduler_config[:listened_queues_only] = value
         
     | 
| 
      
 48 
     | 
    
         
            +
                end
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
                def rufus_scheduler_options
         
     | 
| 
      
 51 
     | 
    
         
            +
                  scheduler_config[:rufus_scheduler_options]
         
     | 
| 
      
 52 
     | 
    
         
            +
                end
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
                def rufus_scheduler_options=(value)
         
     | 
| 
      
 55 
     | 
    
         
            +
                  scheduler_config[:rufus_scheduler_options] = value
         
     | 
| 
      
 56 
     | 
    
         
            +
                end
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
                def sidekiq_queues
         
     | 
| 
      
 59 
     | 
    
         
            +
                  SidekiqScheduler::SidekiqAdapter.sidekiq_queues(sidekiq_config)
         
     | 
| 
      
 60 
     | 
    
         
            +
                end
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
                private
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
                attr_reader :scheduler_config
         
     | 
| 
      
 65 
     | 
    
         
            +
                attr_reader :sidekiq_config
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
                DEFAULT_OPTIONS = {
         
     | 
| 
      
 68 
     | 
    
         
            +
                  enabled: true,
         
     | 
| 
      
 69 
     | 
    
         
            +
                  dynamic: false,
         
     | 
| 
      
 70 
     | 
    
         
            +
                  dynamic_every: '5s',
         
     | 
| 
      
 71 
     | 
    
         
            +
                  schedule: {},
         
     | 
| 
      
 72 
     | 
    
         
            +
                  rufus_scheduler_options: {}
         
     | 
| 
      
 73 
     | 
    
         
            +
                }.freeze
         
     | 
| 
      
 74 
     | 
    
         
            +
             
     | 
| 
      
 75 
     | 
    
         
            +
                def fetch_scheduler_config(sidekiq_config, without_defaults)
         
     | 
| 
      
 76 
     | 
    
         
            +
                  conf = SidekiqScheduler::SidekiqAdapter.fetch_scheduler_config_from_sidekiq(sidekiq_config)
         
     | 
| 
      
 77 
     | 
    
         
            +
                  without_defaults ? conf : DEFAULT_OPTIONS.merge(conf)
         
     | 
| 
      
 78 
     | 
    
         
            +
                end
         
     | 
| 
      
 79 
     | 
    
         
            +
              end
         
     | 
| 
      
 80 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,14 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'sidekiq/web' unless defined?(Sidekiq::Web)
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            ASSETS_PATH = File.expand_path('../../../web/assets', __dir__)
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            Sidekiq::Web.register(SidekiqScheduler::Web)
         
     | 
| 
      
 6 
     | 
    
         
            +
            Sidekiq::Web.tabs['recurring_jobs'] = 'recurring-jobs'
         
     | 
| 
      
 7 
     | 
    
         
            +
            Sidekiq::Web.locales << File.expand_path("#{File.dirname(__FILE__)}/../../../web/locales")
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            if Sidekiq::VERSION >= '6.0.0'
         
     | 
| 
      
 10 
     | 
    
         
            +
              Sidekiq::Web.use Rack::Static, urls: ['/stylesheets-scheduler'],
         
     | 
| 
      
 11 
     | 
    
         
            +
                                             root: ASSETS_PATH,
         
     | 
| 
      
 12 
     | 
    
         
            +
                                             cascade: true,
         
     | 
| 
      
 13 
     | 
    
         
            +
                                             header_rules: [[:all, { 'Cache-Control' => 'public, max-age=86400' }]]
         
     | 
| 
      
 14 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,74 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            begin
         
     | 
| 
      
 2 
     | 
    
         
            +
              require 'sidekiq/web/helpers'
         
     | 
| 
      
 3 
     | 
    
         
            +
            rescue LoadError
         
     | 
| 
      
 4 
     | 
    
         
            +
              require 'sidekiq/web_helpers'
         
     | 
| 
      
 5 
     | 
    
         
            +
            end
         
     | 
| 
      
 6 
     | 
    
         
            +
            require 'sidekiq-scheduler/redis_manager'
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
            module SidekiqScheduler
         
     | 
| 
      
 9 
     | 
    
         
            +
              class JobPresenter
         
     | 
| 
      
 10 
     | 
    
         
            +
                attr_reader :name
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                include Sidekiq::WebHelpers
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                def initialize(name, attributes)
         
     | 
| 
      
 15 
     | 
    
         
            +
                  @name = name
         
     | 
| 
      
 16 
     | 
    
         
            +
                  @attributes = attributes
         
     | 
| 
      
 17 
     | 
    
         
            +
                end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                # Returns the next time execution for the job
         
     | 
| 
      
 20 
     | 
    
         
            +
                #
         
     | 
| 
      
 21 
     | 
    
         
            +
                # @return [String] with the job's next time
         
     | 
| 
      
 22 
     | 
    
         
            +
                def next_time
         
     | 
| 
      
 23 
     | 
    
         
            +
                  execution_time = SidekiqScheduler::RedisManager.get_job_next_time(name)
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                  relative_time(Time.parse(execution_time)) if execution_time
         
     | 
| 
      
 26 
     | 
    
         
            +
                end
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                # Returns the last execution time for the job
         
     | 
| 
      
 29 
     | 
    
         
            +
                #
         
     | 
| 
      
 30 
     | 
    
         
            +
                # @return [String] with the job's last time
         
     | 
| 
      
 31 
     | 
    
         
            +
                def last_time
         
     | 
| 
      
 32 
     | 
    
         
            +
                  execution_time = SidekiqScheduler::RedisManager.get_job_last_time(name)
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                  relative_time(Time.parse(execution_time)) if execution_time
         
     | 
| 
      
 35 
     | 
    
         
            +
                end
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                # Returns the interval for the job
         
     | 
| 
      
 38 
     | 
    
         
            +
                #
         
     | 
| 
      
 39 
     | 
    
         
            +
                # @return [String] with the job's interval
         
     | 
| 
      
 40 
     | 
    
         
            +
                def interval
         
     | 
| 
      
 41 
     | 
    
         
            +
                  @attributes['cron'] || @attributes['interval'] || @attributes['every']
         
     | 
| 
      
 42 
     | 
    
         
            +
                end
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
                # Returns the queue of the job
         
     | 
| 
      
 45 
     | 
    
         
            +
                #
         
     | 
| 
      
 46 
     | 
    
         
            +
                # @return [String] with the job's queue
         
     | 
| 
      
 47 
     | 
    
         
            +
                def queue
         
     | 
| 
      
 48 
     | 
    
         
            +
                  @attributes.fetch('queue', 'default')
         
     | 
| 
      
 49 
     | 
    
         
            +
                end
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
                # Delegates the :[] method to the attributes' hash
         
     | 
| 
      
 52 
     | 
    
         
            +
                #
         
     | 
| 
      
 53 
     | 
    
         
            +
                # @return [String] with the value for that key
         
     | 
| 
      
 54 
     | 
    
         
            +
                def [](key)
         
     | 
| 
      
 55 
     | 
    
         
            +
                  @attributes[key]
         
     | 
| 
      
 56 
     | 
    
         
            +
                end
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
                def enabled?
         
     | 
| 
      
 59 
     | 
    
         
            +
                  SidekiqScheduler::Scheduler.job_enabled?(@name)
         
     | 
| 
      
 60 
     | 
    
         
            +
                end
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
                # Builds the presenter instances for the schedule hash
         
     | 
| 
      
 63 
     | 
    
         
            +
                #
         
     | 
| 
      
 64 
     | 
    
         
            +
                # @param schedule_hash [Hash] with the redis schedule
         
     | 
| 
      
 65 
     | 
    
         
            +
                # @return [Array<JobPresenter>] an array with the instances of presenters
         
     | 
| 
      
 66 
     | 
    
         
            +
                def self.build_collection(schedule_hash)
         
     | 
| 
      
 67 
     | 
    
         
            +
                  schedule_hash ||= {}
         
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
      
 69 
     | 
    
         
            +
                  schedule_hash.sort.map do |name, job_spec|
         
     | 
| 
      
 70 
     | 
    
         
            +
                    new(name, job_spec)
         
     | 
| 
      
 71 
     | 
    
         
            +
                  end
         
     | 
| 
      
 72 
     | 
    
         
            +
                end
         
     | 
| 
      
 73 
     | 
    
         
            +
              end
         
     | 
| 
      
 74 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,44 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'sidekiq-scheduler/schedule'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'sidekiq-scheduler/scheduler'
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            module SidekiqScheduler
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
              # The delayed job router in the system.  This
         
     | 
| 
      
 7 
     | 
    
         
            +
              # manages the scheduled jobs pushed messages
         
     | 
| 
      
 8 
     | 
    
         
            +
              # from Redis onto the work queues
         
     | 
| 
      
 9 
     | 
    
         
            +
              #
         
     | 
| 
      
 10 
     | 
    
         
            +
              class Manager
         
     | 
| 
      
 11 
     | 
    
         
            +
                def initialize(config)
         
     | 
| 
      
 12 
     | 
    
         
            +
                  set_current_scheduler_options(config)
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                  @scheduler_instance = SidekiqScheduler::Scheduler.new(config)
         
     | 
| 
      
 15 
     | 
    
         
            +
                  SidekiqScheduler::Scheduler.instance = @scheduler_instance
         
     | 
| 
      
 16 
     | 
    
         
            +
                  Sidekiq.schedule = config.schedule if @scheduler_instance.enabled
         
     | 
| 
      
 17 
     | 
    
         
            +
                end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                def stop
         
     | 
| 
      
 20 
     | 
    
         
            +
                  @scheduler_instance.clear_schedule!
         
     | 
| 
      
 21 
     | 
    
         
            +
                end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                def start
         
     | 
| 
      
 24 
     | 
    
         
            +
                  @scheduler_instance.load_schedule!
         
     | 
| 
      
 25 
     | 
    
         
            +
                end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                private
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                def set_current_scheduler_options(config)
         
     | 
| 
      
 30 
     | 
    
         
            +
                  enabled = SidekiqScheduler::Scheduler.enabled
         
     | 
| 
      
 31 
     | 
    
         
            +
                  dynamic = SidekiqScheduler::Scheduler.dynamic
         
     | 
| 
      
 32 
     | 
    
         
            +
                  dynamic_every = SidekiqScheduler::Scheduler.dynamic_every
         
     | 
| 
      
 33 
     | 
    
         
            +
                  listened_queues_only = SidekiqScheduler::Scheduler.listened_queues_only
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
                  config.enabled = enabled unless enabled.nil?
         
     | 
| 
      
 36 
     | 
    
         
            +
                  config.dynamic = dynamic unless dynamic.nil?
         
     | 
| 
      
 37 
     | 
    
         
            +
                  config.dynamic_every = dynamic_every unless dynamic_every.nil?
         
     | 
| 
      
 38 
     | 
    
         
            +
                  unless Sidekiq.schedule.nil? || (Sidekiq.schedule.respond_to?(:empty?) && Sidekiq.schedule.empty?)
         
     | 
| 
      
 39 
     | 
    
         
            +
                    config.schedule = Sidekiq.schedule
         
     | 
| 
      
 40 
     | 
    
         
            +
                  end
         
     | 
| 
      
 41 
     | 
    
         
            +
                  config.listened_queues_only = listened_queues_only unless listened_queues_only.nil?
         
     | 
| 
      
 42 
     | 
    
         
            +
                end
         
     | 
| 
      
 43 
     | 
    
         
            +
              end
         
     | 
| 
      
 44 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,241 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module SidekiqScheduler
         
     | 
| 
      
 2 
     | 
    
         
            +
              module RedisManager
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
                REGISTERED_JOBS_THRESHOLD_IN_SECONDS = 24 * 60 * 60
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
                # Returns the schedule of a given job
         
     | 
| 
      
 7 
     | 
    
         
            +
                #
         
     | 
| 
      
 8 
     | 
    
         
            +
                # @param [String] name The name of the job
         
     | 
| 
      
 9 
     | 
    
         
            +
                #
         
     | 
| 
      
 10 
     | 
    
         
            +
                # @return [String] schedule in JSON format
         
     | 
| 
      
 11 
     | 
    
         
            +
                def self.get_job_schedule(name)
         
     | 
| 
      
 12 
     | 
    
         
            +
                  hget(schedules_key, name)
         
     | 
| 
      
 13 
     | 
    
         
            +
                end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                # Returns the state of a given job
         
     | 
| 
      
 16 
     | 
    
         
            +
                #
         
     | 
| 
      
 17 
     | 
    
         
            +
                # @param [String] name The name of the job
         
     | 
| 
      
 18 
     | 
    
         
            +
                #
         
     | 
| 
      
 19 
     | 
    
         
            +
                # @return [String] state in JSON format
         
     | 
| 
      
 20 
     | 
    
         
            +
                def self.get_job_state(name)
         
     | 
| 
      
 21 
     | 
    
         
            +
                  hget(schedules_state_key, name)
         
     | 
| 
      
 22 
     | 
    
         
            +
                end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                # Returns the next execution time for a given job
         
     | 
| 
      
 25 
     | 
    
         
            +
                #
         
     | 
| 
      
 26 
     | 
    
         
            +
                # @param [String] name The name of the job
         
     | 
| 
      
 27 
     | 
    
         
            +
                #
         
     | 
| 
      
 28 
     | 
    
         
            +
                # @return [String] next time the job has to be executed
         
     | 
| 
      
 29 
     | 
    
         
            +
                def self.get_job_next_time(name)
         
     | 
| 
      
 30 
     | 
    
         
            +
                  hget(next_times_key, name)
         
     | 
| 
      
 31 
     | 
    
         
            +
                end
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                # Returns the last execution time of a given job
         
     | 
| 
      
 34 
     | 
    
         
            +
                #
         
     | 
| 
      
 35 
     | 
    
         
            +
                # @param [String] name The name of the job
         
     | 
| 
      
 36 
     | 
    
         
            +
                #
         
     | 
| 
      
 37 
     | 
    
         
            +
                # @return [String] last time the job was executed
         
     | 
| 
      
 38 
     | 
    
         
            +
                def self.get_job_last_time(name)
         
     | 
| 
      
 39 
     | 
    
         
            +
                  hget(last_times_key, name)
         
     | 
| 
      
 40 
     | 
    
         
            +
                end
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
                # Sets the schedule for a given job
         
     | 
| 
      
 43 
     | 
    
         
            +
                #
         
     | 
| 
      
 44 
     | 
    
         
            +
                # @param [String] name The name of the job
         
     | 
| 
      
 45 
     | 
    
         
            +
                # @param [Hash] config The new schedule for the job
         
     | 
| 
      
 46 
     | 
    
         
            +
                def self.set_job_schedule(name, config)
         
     | 
| 
      
 47 
     | 
    
         
            +
                  hset(schedules_key, name, JSON.generate(config))
         
     | 
| 
      
 48 
     | 
    
         
            +
                end
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
                # Sets the state for a given job
         
     | 
| 
      
 51 
     | 
    
         
            +
                #
         
     | 
| 
      
 52 
     | 
    
         
            +
                # @param [String] name The name of the job
         
     | 
| 
      
 53 
     | 
    
         
            +
                # @param [Hash] state The new state for the job
         
     | 
| 
      
 54 
     | 
    
         
            +
                def self.set_job_state(name, state)
         
     | 
| 
      
 55 
     | 
    
         
            +
                  hset(schedules_state_key, name, JSON.generate(state))
         
     | 
| 
      
 56 
     | 
    
         
            +
                end
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
                # Sets the next execution time for a given job
         
     | 
| 
      
 59 
     | 
    
         
            +
                #
         
     | 
| 
      
 60 
     | 
    
         
            +
                # @param [String] name The name of the job
         
     | 
| 
      
 61 
     | 
    
         
            +
                # @param [String] next_time The next time the job has to be executed
         
     | 
| 
      
 62 
     | 
    
         
            +
                def self.set_job_next_time(name, next_time)
         
     | 
| 
      
 63 
     | 
    
         
            +
                  hset(next_times_key, name, String(next_time))
         
     | 
| 
      
 64 
     | 
    
         
            +
                end
         
     | 
| 
      
 65 
     | 
    
         
            +
             
     | 
| 
      
 66 
     | 
    
         
            +
                # Sets the last execution time for a given job
         
     | 
| 
      
 67 
     | 
    
         
            +
                #
         
     | 
| 
      
 68 
     | 
    
         
            +
                # @param [String] name The name of the job
         
     | 
| 
      
 69 
     | 
    
         
            +
                # @param [String] last_time The last time the job was executed
         
     | 
| 
      
 70 
     | 
    
         
            +
                def self.set_job_last_time(name, last_time)
         
     | 
| 
      
 71 
     | 
    
         
            +
                  hset(last_times_key, name, String(last_time))
         
     | 
| 
      
 72 
     | 
    
         
            +
                end
         
     | 
| 
      
 73 
     | 
    
         
            +
             
     | 
| 
      
 74 
     | 
    
         
            +
                # Removes the schedule for a given job
         
     | 
| 
      
 75 
     | 
    
         
            +
                #
         
     | 
| 
      
 76 
     | 
    
         
            +
                # @param [String] name The name of the job
         
     | 
| 
      
 77 
     | 
    
         
            +
                def self.remove_job_schedule(name)
         
     | 
| 
      
 78 
     | 
    
         
            +
                  hdel(schedules_key, name)
         
     | 
| 
      
 79 
     | 
    
         
            +
                end
         
     | 
| 
      
 80 
     | 
    
         
            +
             
     | 
| 
      
 81 
     | 
    
         
            +
                # Removes the next execution time for a given job
         
     | 
| 
      
 82 
     | 
    
         
            +
                #
         
     | 
| 
      
 83 
     | 
    
         
            +
                # @param [String] name The name of the job
         
     | 
| 
      
 84 
     | 
    
         
            +
                def self.remove_job_next_time(name)
         
     | 
| 
      
 85 
     | 
    
         
            +
                  hdel(next_times_key, name)
         
     | 
| 
      
 86 
     | 
    
         
            +
                end
         
     | 
| 
      
 87 
     | 
    
         
            +
             
     | 
| 
      
 88 
     | 
    
         
            +
                # Returns the schedules of all the jobs
         
     | 
| 
      
 89 
     | 
    
         
            +
                #
         
     | 
| 
      
 90 
     | 
    
         
            +
                # @return [Hash] hash with all the job schedules
         
     | 
| 
      
 91 
     | 
    
         
            +
                def self.get_all_schedules
         
     | 
| 
      
 92 
     | 
    
         
            +
                  Sidekiq.redis { |r| r.hgetall(schedules_key) }
         
     | 
| 
      
 93 
     | 
    
         
            +
                end
         
     | 
| 
      
 94 
     | 
    
         
            +
             
     | 
| 
      
 95 
     | 
    
         
            +
                # Returns boolean value that indicates if the schedules value exists
         
     | 
| 
      
 96 
     | 
    
         
            +
                #
         
     | 
| 
      
 97 
     | 
    
         
            +
                # @return [Boolean] true if the schedules key is set, false otherwise
         
     | 
| 
      
 98 
     | 
    
         
            +
                def self.schedule_exist?
         
     | 
| 
      
 99 
     | 
    
         
            +
                  SidekiqScheduler::SidekiqAdapter.redis_key_exists?(schedules_key)
         
     | 
| 
      
 100 
     | 
    
         
            +
                end
         
     | 
| 
      
 101 
     | 
    
         
            +
             
     | 
| 
      
 102 
     | 
    
         
            +
                # Returns all the schedule changes for a given time range.
         
     | 
| 
      
 103 
     | 
    
         
            +
                #
         
     | 
| 
      
 104 
     | 
    
         
            +
                # @param [Float] from The minimum value in the range
         
     | 
| 
      
 105 
     | 
    
         
            +
                # @param [Float] to The maximum value in the range
         
     | 
| 
      
 106 
     | 
    
         
            +
                #
         
     | 
| 
      
 107 
     | 
    
         
            +
                # @return [Array] array with all the changed job names
         
     | 
| 
      
 108 
     | 
    
         
            +
                def self.get_schedule_changes(from, to)
         
     | 
| 
      
 109 
     | 
    
         
            +
                  Sidekiq.redis { |r| r.zrangebyscore(schedules_changed_key, from, "(#{to}") }
         
     | 
| 
      
 110 
     | 
    
         
            +
                end
         
     | 
| 
      
 111 
     | 
    
         
            +
             
     | 
| 
      
 112 
     | 
    
         
            +
                # Register a schedule change for a given job
         
     | 
| 
      
 113 
     | 
    
         
            +
                #
         
     | 
| 
      
 114 
     | 
    
         
            +
                # @param [String] name The name of the job
         
     | 
| 
      
 115 
     | 
    
         
            +
                def self.add_schedule_change(name)
         
     | 
| 
      
 116 
     | 
    
         
            +
                  Sidekiq.redis { |r| r.zadd(schedules_changed_key, Time.now.to_f, name) }
         
     | 
| 
      
 117 
     | 
    
         
            +
                end
         
     | 
| 
      
 118 
     | 
    
         
            +
             
     | 
| 
      
 119 
     | 
    
         
            +
                # Remove all the schedule changes records
         
     | 
| 
      
 120 
     | 
    
         
            +
                def self.clean_schedules_changed
         
     | 
| 
      
 121 
     | 
    
         
            +
                  Sidekiq.redis { |r| r.del(schedules_changed_key) unless r.type(schedules_changed_key) == 'zset' }
         
     | 
| 
      
 122 
     | 
    
         
            +
                end
         
     | 
| 
      
 123 
     | 
    
         
            +
             
     | 
| 
      
 124 
     | 
    
         
            +
                # Removes a queued job instance
         
     | 
| 
      
 125 
     | 
    
         
            +
                #
         
     | 
| 
      
 126 
     | 
    
         
            +
                # @param [String] job_name The name of the job
         
     | 
| 
      
 127 
     | 
    
         
            +
                # @param [Time] time The time at which the job was cleared by the scheduler
         
     | 
| 
      
 128 
     | 
    
         
            +
                #
         
     | 
| 
      
 129 
     | 
    
         
            +
                # @return [Boolean] true if the job was registered, false otherwise
         
     | 
| 
      
 130 
     | 
    
         
            +
                def self.register_job_instance(job_name, time)
         
     | 
| 
      
 131 
     | 
    
         
            +
                  job_key = pushed_job_key(job_name)
         
     | 
| 
      
 132 
     | 
    
         
            +
                  registered, _ = Sidekiq.redis do |r|
         
     | 
| 
      
 133 
     | 
    
         
            +
                    r.pipelined do |pipeline|
         
     | 
| 
      
 134 
     | 
    
         
            +
                      pipeline.zadd(job_key, time.to_i, time.to_i)
         
     | 
| 
      
 135 
     | 
    
         
            +
                      pipeline.expire(job_key, REGISTERED_JOBS_THRESHOLD_IN_SECONDS)
         
     | 
| 
      
 136 
     | 
    
         
            +
                    end
         
     | 
| 
      
 137 
     | 
    
         
            +
                  end
         
     | 
| 
      
 138 
     | 
    
         
            +
             
     | 
| 
      
 139 
     | 
    
         
            +
                  registered.instance_of?(Integer) ? (registered > 0) : registered
         
     | 
| 
      
 140 
     | 
    
         
            +
                end
         
     | 
| 
      
 141 
     | 
    
         
            +
             
     | 
| 
      
 142 
     | 
    
         
            +
                # Removes instances of the job older than 24 hours
         
     | 
| 
      
 143 
     | 
    
         
            +
                #
         
     | 
| 
      
 144 
     | 
    
         
            +
                # @param [String] job_name The name of the job
         
     | 
| 
      
 145 
     | 
    
         
            +
                def self.remove_elder_job_instances(job_name)
         
     | 
| 
      
 146 
     | 
    
         
            +
                  seconds_ago = Time.now.to_i - REGISTERED_JOBS_THRESHOLD_IN_SECONDS
         
     | 
| 
      
 147 
     | 
    
         
            +
             
     | 
| 
      
 148 
     | 
    
         
            +
                  Sidekiq.redis do |r|
         
     | 
| 
      
 149 
     | 
    
         
            +
                    r.zremrangebyscore(pushed_job_key(job_name), 0, seconds_ago)
         
     | 
| 
      
 150 
     | 
    
         
            +
                  end
         
     | 
| 
      
 151 
     | 
    
         
            +
                end
         
     | 
| 
      
 152 
     | 
    
         
            +
             
     | 
| 
      
 153 
     | 
    
         
            +
                # Returns the key of the Redis sorted set used to store job enqueues
         
     | 
| 
      
 154 
     | 
    
         
            +
                #
         
     | 
| 
      
 155 
     | 
    
         
            +
                # @param [String] job_name The name of the job
         
     | 
| 
      
 156 
     | 
    
         
            +
                #
         
     | 
| 
      
 157 
     | 
    
         
            +
                # @return [String] the pushed job key
         
     | 
| 
      
 158 
     | 
    
         
            +
                def self.pushed_job_key(job_name)
         
     | 
| 
      
 159 
     | 
    
         
            +
                  "#{key_prefix}sidekiq-scheduler:pushed:#{job_name}"
         
     | 
| 
      
 160 
     | 
    
         
            +
                end
         
     | 
| 
      
 161 
     | 
    
         
            +
             
     | 
| 
      
 162 
     | 
    
         
            +
                # Returns the key of the Redis hash for job's execution times hash
         
     | 
| 
      
 163 
     | 
    
         
            +
                #
         
     | 
| 
      
 164 
     | 
    
         
            +
                # @return [String] with the key
         
     | 
| 
      
 165 
     | 
    
         
            +
                def self.next_times_key
         
     | 
| 
      
 166 
     | 
    
         
            +
                  "#{key_prefix}sidekiq-scheduler:next_times"
         
     | 
| 
      
 167 
     | 
    
         
            +
                end
         
     | 
| 
      
 168 
     | 
    
         
            +
             
     | 
| 
      
 169 
     | 
    
         
            +
                # Returns the key of the Redis hash for job's last execution times hash
         
     | 
| 
      
 170 
     | 
    
         
            +
                #
         
     | 
| 
      
 171 
     | 
    
         
            +
                # @return [String] with the key
         
     | 
| 
      
 172 
     | 
    
         
            +
                def self.last_times_key
         
     | 
| 
      
 173 
     | 
    
         
            +
                  "#{key_prefix}sidekiq-scheduler:last_times"
         
     | 
| 
      
 174 
     | 
    
         
            +
                end
         
     | 
| 
      
 175 
     | 
    
         
            +
             
     | 
| 
      
 176 
     | 
    
         
            +
                # Returns the Redis's key for saving schedule states.
         
     | 
| 
      
 177 
     | 
    
         
            +
                #
         
     | 
| 
      
 178 
     | 
    
         
            +
                # @return [String] with the key
         
     | 
| 
      
 179 
     | 
    
         
            +
                def self.schedules_state_key
         
     | 
| 
      
 180 
     | 
    
         
            +
                  "#{key_prefix}sidekiq-scheduler:states"
         
     | 
| 
      
 181 
     | 
    
         
            +
                end
         
     | 
| 
      
 182 
     | 
    
         
            +
             
     | 
| 
      
 183 
     | 
    
         
            +
                # Returns the Redis's key for saving schedules.
         
     | 
| 
      
 184 
     | 
    
         
            +
                #
         
     | 
| 
      
 185 
     | 
    
         
            +
                # @return [String] with the key
         
     | 
| 
      
 186 
     | 
    
         
            +
                def self.schedules_key
         
     | 
| 
      
 187 
     | 
    
         
            +
                  "#{key_prefix}schedules"
         
     | 
| 
      
 188 
     | 
    
         
            +
                end
         
     | 
| 
      
 189 
     | 
    
         
            +
             
     | 
| 
      
 190 
     | 
    
         
            +
                # Returns the Redis's key for saving schedule changes.
         
     | 
| 
      
 191 
     | 
    
         
            +
                #
         
     | 
| 
      
 192 
     | 
    
         
            +
                # @return [String] with the key
         
     | 
| 
      
 193 
     | 
    
         
            +
                def self.schedules_changed_key
         
     | 
| 
      
 194 
     | 
    
         
            +
                  "#{key_prefix}schedules_changed"
         
     | 
| 
      
 195 
     | 
    
         
            +
                end
         
     | 
| 
      
 196 
     | 
    
         
            +
             
     | 
| 
      
 197 
     | 
    
         
            +
                # Returns the key prefix used to generate all scheduler keys
         
     | 
| 
      
 198 
     | 
    
         
            +
                #
         
     | 
| 
      
 199 
     | 
    
         
            +
                # @return [String] with the key prefix
         
     | 
| 
      
 200 
     | 
    
         
            +
                def self.key_prefix
         
     | 
| 
      
 201 
     | 
    
         
            +
                  @key_prefix
         
     | 
| 
      
 202 
     | 
    
         
            +
                end
         
     | 
| 
      
 203 
     | 
    
         
            +
             
     | 
| 
      
 204 
     | 
    
         
            +
                # Sets the key prefix used to scope all scheduler keys
         
     | 
| 
      
 205 
     | 
    
         
            +
                #
         
     | 
| 
      
 206 
     | 
    
         
            +
                # @param [String] value The string to use as the prefix. A ":" will be appended as a delimiter if needed.
         
     | 
| 
      
 207 
     | 
    
         
            +
                def self.key_prefix=(value)
         
     | 
| 
      
 208 
     | 
    
         
            +
                  value = "#{value}:" if value && !%w[. :].include?(value[-1])
         
     | 
| 
      
 209 
     | 
    
         
            +
                  @key_prefix = value
         
     | 
| 
      
 210 
     | 
    
         
            +
                end
         
     | 
| 
      
 211 
     | 
    
         
            +
             
     | 
| 
      
 212 
     | 
    
         
            +
                private
         
     | 
| 
      
 213 
     | 
    
         
            +
             
     | 
| 
      
 214 
     | 
    
         
            +
                # Returns the value of a Redis stored hash field
         
     | 
| 
      
 215 
     | 
    
         
            +
                #
         
     | 
| 
      
 216 
     | 
    
         
            +
                # @param [String] hash_key The key name of the hash
         
     | 
| 
      
 217 
     | 
    
         
            +
                # @param [String] field_key The key name of the field
         
     | 
| 
      
 218 
     | 
    
         
            +
                #
         
     | 
| 
      
 219 
     | 
    
         
            +
                # @return [String]
         
     | 
| 
      
 220 
     | 
    
         
            +
                def self.hget(hash_key, field_key)
         
     | 
| 
      
 221 
     | 
    
         
            +
                  Sidekiq.redis { |r| r.hget(hash_key, field_key) }
         
     | 
| 
      
 222 
     | 
    
         
            +
                end
         
     | 
| 
      
 223 
     | 
    
         
            +
             
     | 
| 
      
 224 
     | 
    
         
            +
                # Sets the value of a Redis stored hash field
         
     | 
| 
      
 225 
     | 
    
         
            +
                #
         
     | 
| 
      
 226 
     | 
    
         
            +
                # @param [String] hash_key The key name of the hash
         
     | 
| 
      
 227 
     | 
    
         
            +
                # @param [String] field_key The key name of the field
         
     | 
| 
      
 228 
     | 
    
         
            +
                # @param [String] value The new value name for the field
         
     | 
| 
      
 229 
     | 
    
         
            +
                def self.hset(hash_key, field_key, value)
         
     | 
| 
      
 230 
     | 
    
         
            +
                  Sidekiq.redis { |r| r.hset(hash_key, field_key, value) }
         
     | 
| 
      
 231 
     | 
    
         
            +
                end
         
     | 
| 
      
 232 
     | 
    
         
            +
             
     | 
| 
      
 233 
     | 
    
         
            +
                # Removes the value of a Redis stored hash field
         
     | 
| 
      
 234 
     | 
    
         
            +
                #
         
     | 
| 
      
 235 
     | 
    
         
            +
                # @param [String] hash_key The key name of the hash
         
     | 
| 
      
 236 
     | 
    
         
            +
                # @param [String] field_key The key name of the field
         
     | 
| 
      
 237 
     | 
    
         
            +
                def self.hdel(hash_key, field_key)
         
     | 
| 
      
 238 
     | 
    
         
            +
                  Sidekiq.redis { |r| r.hdel(hash_key, field_key) }
         
     | 
| 
      
 239 
     | 
    
         
            +
                end
         
     | 
| 
      
 240 
     | 
    
         
            +
              end
         
     | 
| 
      
 241 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,29 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'sidekiq-scheduler/utils'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module SidekiqScheduler
         
     | 
| 
      
 4 
     | 
    
         
            +
              class RufusUtils
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
                # Normalizes schedule options to rufus scheduler options
         
     | 
| 
      
 7 
     | 
    
         
            +
                #
         
     | 
| 
      
 8 
     | 
    
         
            +
                # @param options [String, Array]
         
     | 
| 
      
 9 
     | 
    
         
            +
                #
         
     | 
| 
      
 10 
     | 
    
         
            +
                # @return [Array]
         
     | 
| 
      
 11 
     | 
    
         
            +
                #
         
     | 
| 
      
 12 
     | 
    
         
            +
                # @example
         
     | 
| 
      
 13 
     | 
    
         
            +
                #   normalize_schedule_options('15m') => ['15m', {}]
         
     | 
| 
      
 14 
     | 
    
         
            +
                #   normalize_schedule_options(['15m']) => ['15m', {}]
         
     | 
| 
      
 15 
     | 
    
         
            +
                #   normalize_schedule_options(['15m', first_in: '5m']) => ['15m', { first_in: '5m' }]
         
     | 
| 
      
 16 
     | 
    
         
            +
                def self.normalize_schedule_options(options)
         
     | 
| 
      
 17 
     | 
    
         
            +
                  schedule, opts = options
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                  if !opts.is_a?(Hash)
         
     | 
| 
      
 20 
     | 
    
         
            +
                    opts = {}
         
     | 
| 
      
 21 
     | 
    
         
            +
                  end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                  opts = SidekiqScheduler::Utils.symbolize_keys(opts)
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                  return schedule, opts
         
     | 
| 
      
 26 
     | 
    
         
            +
                end
         
     | 
| 
      
 27 
     | 
    
         
            +
              end
         
     | 
| 
      
 28 
     | 
    
         
            +
            end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
         @@ -0,0 +1,154 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'json'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require 'sidekiq-scheduler/utils'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require_relative 'redis_manager'
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            module SidekiqScheduler
         
     | 
| 
      
 7 
     | 
    
         
            +
              module Schedule
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                # Accepts a new schedule configuration of the form:
         
     | 
| 
      
 10 
     | 
    
         
            +
                #
         
     | 
| 
      
 11 
     | 
    
         
            +
                #   {
         
     | 
| 
      
 12 
     | 
    
         
            +
                #     "MakeTea" => {
         
     | 
| 
      
 13 
     | 
    
         
            +
                #       "every" => "1m" },
         
     | 
| 
      
 14 
     | 
    
         
            +
                #     "some_name" => {
         
     | 
| 
      
 15 
     | 
    
         
            +
                #       "cron"        => "5/* * * *",
         
     | 
| 
      
 16 
     | 
    
         
            +
                #       "class"       => "DoSomeWork",
         
     | 
| 
      
 17 
     | 
    
         
            +
                #       "args"        => "work on this string",
         
     | 
| 
      
 18 
     | 
    
         
            +
                #       "description" => "this thing works it"s butter off" },
         
     | 
| 
      
 19 
     | 
    
         
            +
                #     ...
         
     | 
| 
      
 20 
     | 
    
         
            +
                #   }
         
     | 
| 
      
 21 
     | 
    
         
            +
                #
         
     | 
| 
      
 22 
     | 
    
         
            +
                # Hash keys can be anything and are used to describe and reference
         
     | 
| 
      
 23 
     | 
    
         
            +
                # the scheduled job. If the "class" argument is missing, the key
         
     | 
| 
      
 24 
     | 
    
         
            +
                # is used implicitly as "class" argument - in the "MakeTea" example,
         
     | 
| 
      
 25 
     | 
    
         
            +
                # "MakeTea" is used both as job name and sidekiq worker class.
         
     | 
| 
      
 26 
     | 
    
         
            +
                #
         
     | 
| 
      
 27 
     | 
    
         
            +
                # :cron can be any cron scheduling string
         
     | 
| 
      
 28 
     | 
    
         
            +
                #
         
     | 
| 
      
 29 
     | 
    
         
            +
                # :every can be used in lieu of :cron. see rufus-scheduler's 'every' usage
         
     | 
| 
      
 30 
     | 
    
         
            +
                # for valid syntax. If :cron is present it will take precedence over :every.
         
     | 
| 
      
 31 
     | 
    
         
            +
                #
         
     | 
| 
      
 32 
     | 
    
         
            +
                # :class must be a sidekiq worker class. If it is missing, the job name (hash key)
         
     | 
| 
      
 33 
     | 
    
         
            +
                # will be used as :class.
         
     | 
| 
      
 34 
     | 
    
         
            +
                #
         
     | 
| 
      
 35 
     | 
    
         
            +
                # :args can be any yaml which will be converted to a ruby literal and
         
     | 
| 
      
 36 
     | 
    
         
            +
                # passed in a params. (optional)
         
     | 
| 
      
 37 
     | 
    
         
            +
                #
         
     | 
| 
      
 38 
     | 
    
         
            +
                # :description is just that, a description of the job (optional). If
         
     | 
| 
      
 39 
     | 
    
         
            +
                # params is an array, each element in the array is passed as a separate
         
     | 
| 
      
 40 
     | 
    
         
            +
                # param, otherwise params is passed in as the only parameter to perform.
         
     | 
| 
      
 41 
     | 
    
         
            +
                def schedule=(schedule_hash)
         
     | 
| 
      
 42 
     | 
    
         
            +
                  schedule_hash = prepare_schedule(schedule_hash)
         
     | 
| 
      
 43 
     | 
    
         
            +
                  to_remove = get_all_schedules.keys - schedule_hash.keys.map(&:to_s)
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                  schedule_hash.each do |name, job_spec|
         
     | 
| 
      
 46 
     | 
    
         
            +
                    set_schedule(name, job_spec)
         
     | 
| 
      
 47 
     | 
    
         
            +
                  end
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
                  to_remove.each do |name|
         
     | 
| 
      
 50 
     | 
    
         
            +
                    remove_schedule(name)
         
     | 
| 
      
 51 
     | 
    
         
            +
                  end
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
                  @schedule = schedule_hash
         
     | 
| 
      
 54 
     | 
    
         
            +
                end
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
      
 56 
     | 
    
         
            +
                def schedule
         
     | 
| 
      
 57 
     | 
    
         
            +
                  @schedule
         
     | 
| 
      
 58 
     | 
    
         
            +
                end
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
                # Reloads the schedule from Redis and return it.
         
     | 
| 
      
 61 
     | 
    
         
            +
                #
         
     | 
| 
      
 62 
     | 
    
         
            +
                # @return Hash
         
     | 
| 
      
 63 
     | 
    
         
            +
                def reload_schedule!
         
     | 
| 
      
 64 
     | 
    
         
            +
                  @schedule = get_schedule
         
     | 
| 
      
 65 
     | 
    
         
            +
                end
         
     | 
| 
      
 66 
     | 
    
         
            +
                alias_method :schedule!, :reload_schedule!
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
                # Retrive the schedule configuration for the given name
         
     | 
| 
      
 69 
     | 
    
         
            +
                # if the name is nil it returns a hash with all the
         
     | 
| 
      
 70 
     | 
    
         
            +
                # names end their schedules.
         
     | 
| 
      
 71 
     | 
    
         
            +
                def get_schedule(name = nil)
         
     | 
| 
      
 72 
     | 
    
         
            +
                  if name.nil?
         
     | 
| 
      
 73 
     | 
    
         
            +
                    get_all_schedules
         
     | 
| 
      
 74 
     | 
    
         
            +
                  else
         
     | 
| 
      
 75 
     | 
    
         
            +
                    encoded_schedule = SidekiqScheduler::RedisManager.get_job_schedule(name)
         
     | 
| 
      
 76 
     | 
    
         
            +
                    encoded_schedule.nil? ? nil : JSON.parse(encoded_schedule)
         
     | 
| 
      
 77 
     | 
    
         
            +
                  end
         
     | 
| 
      
 78 
     | 
    
         
            +
                end
         
     | 
| 
      
 79 
     | 
    
         
            +
             
     | 
| 
      
 80 
     | 
    
         
            +
                # gets the schedule as it exists in redis
         
     | 
| 
      
 81 
     | 
    
         
            +
                def get_all_schedules
         
     | 
| 
      
 82 
     | 
    
         
            +
                  schedules = {}
         
     | 
| 
      
 83 
     | 
    
         
            +
             
     | 
| 
      
 84 
     | 
    
         
            +
                  if SidekiqScheduler::RedisManager.schedule_exist?
         
     | 
| 
      
 85 
     | 
    
         
            +
                    SidekiqScheduler::RedisManager.get_all_schedules.tap do |h|
         
     | 
| 
      
 86 
     | 
    
         
            +
                      h.each do |name, config|
         
     | 
| 
      
 87 
     | 
    
         
            +
                        schedules[name] = JSON.parse(config)
         
     | 
| 
      
 88 
     | 
    
         
            +
                      end
         
     | 
| 
      
 89 
     | 
    
         
            +
                    end
         
     | 
| 
      
 90 
     | 
    
         
            +
                  end
         
     | 
| 
      
 91 
     | 
    
         
            +
             
     | 
| 
      
 92 
     | 
    
         
            +
                  schedules
         
     | 
| 
      
 93 
     | 
    
         
            +
                end
         
     | 
| 
      
 94 
     | 
    
         
            +
             
     | 
| 
      
 95 
     | 
    
         
            +
                # Create or update a schedule with the provided name and configuration.
         
     | 
| 
      
 96 
     | 
    
         
            +
                #
         
     | 
| 
      
 97 
     | 
    
         
            +
                # Note: values for class and custom_job_class need to be strings,
         
     | 
| 
      
 98 
     | 
    
         
            +
                # not constants.
         
     | 
| 
      
 99 
     | 
    
         
            +
                #
         
     | 
| 
      
 100 
     | 
    
         
            +
                #    Sidekiq.set_schedule('some_job', { :class => 'SomeJob',
         
     | 
| 
      
 101 
     | 
    
         
            +
                #                                       :every => '15mins',
         
     | 
| 
      
 102 
     | 
    
         
            +
                #                                       :queue => 'high',
         
     | 
| 
      
 103 
     | 
    
         
            +
                #                                       :args => '/tmp/poop' })
         
     | 
| 
      
 104 
     | 
    
         
            +
                def set_schedule(name, config)
         
     | 
| 
      
 105 
     | 
    
         
            +
                  existing_config = get_schedule(name)
         
     | 
| 
      
 106 
     | 
    
         
            +
                  unless existing_config && existing_config == config
         
     | 
| 
      
 107 
     | 
    
         
            +
                    SidekiqScheduler::RedisManager.set_job_schedule(name, config)
         
     | 
| 
      
 108 
     | 
    
         
            +
                    SidekiqScheduler::RedisManager.add_schedule_change(name)
         
     | 
| 
      
 109 
     | 
    
         
            +
                  end
         
     | 
| 
      
 110 
     | 
    
         
            +
                  config
         
     | 
| 
      
 111 
     | 
    
         
            +
                end
         
     | 
| 
      
 112 
     | 
    
         
            +
             
     | 
| 
      
 113 
     | 
    
         
            +
                # remove a given schedule by name
         
     | 
| 
      
 114 
     | 
    
         
            +
                def remove_schedule(name)
         
     | 
| 
      
 115 
     | 
    
         
            +
                  SidekiqScheduler::RedisManager.remove_job_schedule(name)
         
     | 
| 
      
 116 
     | 
    
         
            +
                  SidekiqScheduler::RedisManager.add_schedule_change(name)
         
     | 
| 
      
 117 
     | 
    
         
            +
                end
         
     | 
| 
      
 118 
     | 
    
         
            +
             
     | 
| 
      
 119 
     | 
    
         
            +
                private
         
     | 
| 
      
 120 
     | 
    
         
            +
             
     | 
| 
      
 121 
     | 
    
         
            +
                def prepare_schedule(schedule_hash)
         
     | 
| 
      
 122 
     | 
    
         
            +
                  schedule_hash = SidekiqScheduler::Utils.stringify_keys(schedule_hash)
         
     | 
| 
      
 123 
     | 
    
         
            +
             
     | 
| 
      
 124 
     | 
    
         
            +
                  prepared_hash = {}
         
     | 
| 
      
 125 
     | 
    
         
            +
             
     | 
| 
      
 126 
     | 
    
         
            +
                  schedule_hash.each do |name, job_spec|
         
     | 
| 
      
 127 
     | 
    
         
            +
                    job_spec = job_spec.dup
         
     | 
| 
      
 128 
     | 
    
         
            +
             
     | 
| 
      
 129 
     | 
    
         
            +
                    job_class = job_spec.fetch('class', name)
         
     | 
| 
      
 130 
     | 
    
         
            +
                    inferred_queue = infer_queue(job_class)
         
     | 
| 
      
 131 
     | 
    
         
            +
             
     | 
| 
      
 132 
     | 
    
         
            +
                    job_spec['class'] ||= job_class
         
     | 
| 
      
 133 
     | 
    
         
            +
                    job_spec['queue'] ||= inferred_queue unless inferred_queue.nil?
         
     | 
| 
      
 134 
     | 
    
         
            +
             
     | 
| 
      
 135 
     | 
    
         
            +
                    prepared_hash[name] = job_spec
         
     | 
| 
      
 136 
     | 
    
         
            +
                  end
         
     | 
| 
      
 137 
     | 
    
         
            +
                  prepared_hash
         
     | 
| 
      
 138 
     | 
    
         
            +
                end
         
     | 
| 
      
 139 
     | 
    
         
            +
             
     | 
| 
      
 140 
     | 
    
         
            +
                def infer_queue(klass)
         
     | 
| 
      
 141 
     | 
    
         
            +
                  klass = try_to_constantize(klass)
         
     | 
| 
      
 142 
     | 
    
         
            +
             
     | 
| 
      
 143 
     | 
    
         
            +
                  # ActiveJob uses queue_as when the job is created
         
     | 
| 
      
 144 
     | 
    
         
            +
                  # to determine the queue
         
     | 
| 
      
 145 
     | 
    
         
            +
                  if klass.respond_to?(:sidekiq_options) && !SidekiqScheduler::Utils.active_job_enqueue?(klass)
         
     | 
| 
      
 146 
     | 
    
         
            +
                    klass.sidekiq_options['queue']
         
     | 
| 
      
 147 
     | 
    
         
            +
                  end
         
     | 
| 
      
 148 
     | 
    
         
            +
                end
         
     | 
| 
      
 149 
     | 
    
         
            +
             
     | 
| 
      
 150 
     | 
    
         
            +
                def try_to_constantize(klass)
         
     | 
| 
      
 151 
     | 
    
         
            +
                  SidekiqScheduler::Utils.try_to_constantize(klass)
         
     | 
| 
      
 152 
     | 
    
         
            +
                end
         
     | 
| 
      
 153 
     | 
    
         
            +
              end
         
     | 
| 
      
 154 
     | 
    
         
            +
            end
         
     |