Module: Resque::Scheduler::SchedulingExtensions

Included in:
Extension
Defined in:
lib/resque/scheduler/scheduling_extensions.rb

Instance Method Summary collapse

Instance Method Details

#all_schedulesObject

gets the schedules as it exists in redis


92
93
94
95
96
97
98
99
100
# File 'lib/resque/scheduler/scheduling_extensions.rb', line 92

def all_schedules
  return nil unless redis.exists(:schedules)

  redis.hgetall(:schedules).tap do |h|
    h.each do |name, config|
      h[name] = decode(config)
    end
  end
end

#clean_schedules(keys = non_persistent_schedules) ⇒ Object

clean the schedules as it exists in redis, useful for first setup?


103
104
105
106
107
108
109
# File 'lib/resque/scheduler/scheduling_extensions.rb', line 103

def clean_schedules(keys = non_persistent_schedules)
  keys.each do |key|
    remove_schedule(key)
  end
  @schedule = nil
  true
end

#fetch_schedule(name) ⇒ Object

retrive the schedule configuration for the given name


135
136
137
# File 'lib/resque/scheduler/scheduling_extensions.rb', line 135

def fetch_schedule(name)
  decode(redis.hget(:schedules, name))
end

#non_persistent_schedulesObject


111
112
113
# File 'lib/resque/scheduler/scheduling_extensions.rb', line 111

def non_persistent_schedules
  redis.hkeys(:schedules).select { |k| !schedule_persisted?(k) }
end

#reload_schedule!Object

reloads the schedule from redis


87
88
89
# File 'lib/resque/scheduler/scheduling_extensions.rb', line 87

def reload_schedule!
  @schedule = all_schedules
end

#remove_schedule(name) ⇒ Object

remove a given schedule by name


144
145
146
147
148
# File 'lib/resque/scheduler/scheduling_extensions.rb', line 144

def remove_schedule(name)
  redis.hdel(:schedules, name)
  redis.srem(:persisted_schedules, name)
  redis.sadd(:schedules_changed, name)
end

#scheduleObject

Returns the schedule hash


81
82
83
84
# File 'lib/resque/scheduler/scheduling_extensions.rb', line 81

def schedule
  @schedule ||= all_schedules
  @schedule || {}
end

#schedule=(schedule_hash) ⇒ Object

Accepts a new schedule configuration of the form:

{
  "MakeTea" => {
    "every" => "1m" },
  "some_name" => {
    "cron"        => "5/* * * *",
    "class"       => "DoSomeWork",
    "args"        => "work on this string",
    "description" => "this thing works it"s butter off" },
  ...
}

Hash keys can be anything and are used to describe and reference the scheduled job. If the “class” argument is missing, the key is used implicitly as “class” argument - in the “MakeTea” example, “MakeTea” is used both as job name and resque worker class.

Any jobs that were in the old schedule, but are not present in the new schedule, will be removed.

:cron can be any cron scheduling string

:every can be used in lieu of :cron. see rufus-scheduler's 'every' usage for valid syntax. If :cron is present it will take precedence over :every.

:class must be a resque worker class. If it is missing, the job name (hash key) will be used as :class.

:args can be any yaml which will be converted to a ruby literal and passed in a params. (optional)

:rails_envs is the list of envs where the job gets loaded. Envs are comma separated (optional)

:description is just that, a description of the job (optional). If params is an array, each element in the array is passed as a separate param, otherwise params is passed in as the only parameter to perform.


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
# File 'lib/resque/scheduler/scheduling_extensions.rb', line 46

def schedule=(schedule_hash)
  # This operation tries to be as atomic as possible.
  # It needs to read the existing schedules outside the transaction.
  # Unlikely, but this could still cause a race condition.
  #
  # A more robust solution would be to SCRIPT it, but that would change
  # the required version of Redis.

  # select schedules to remove
  if redis.exists(:schedules)
    clean_keys = non_persistent_schedules
  else
    clean_keys = []
  end

  # Start the transaction. If this is not atomic and more than one
  # process is calling `schedule=` the clean_schedules might overlap a
  # set_schedule and cause the schedules to become corrupt.
  redis.multi do
    clean_schedules(clean_keys)

    schedule_hash = prepare_schedule(schedule_hash)

    # store all schedules in redis, so we can retrieve them back
    # everywhere.
    schedule_hash.each do |name, job_spec|
      set_schedule(name, job_spec)
    end
  end

  # ensure only return the successfully saved data!
  reload_schedule!
end

#schedule_persisted?(name) ⇒ Boolean

Returns:

  • (Boolean)

139
140
141
# File 'lib/resque/scheduler/scheduling_extensions.rb', line 139

def schedule_persisted?(name)
  redis.sismember(:persisted_schedules, name)
end

#set_schedule(name, config) ⇒ Object

Create or update a schedule with the provided name and configuration.

Note: values for class and custom_job_class need to be strings, not constants.

Resque.set_schedule('some_job', {:class => 'SomeJob',
                                 :every => '15mins',
                                 :queue => 'high',
                                 :args => '/tmp/poop'})

124
125
126
127
128
129
130
131
132
# File 'lib/resque/scheduler/scheduling_extensions.rb', line 124

def set_schedule(name, config)
  persist = config.delete(:persist) || config.delete('persist')
  redis.pipelined do
    redis.hset(:schedules, name, encode(config))
    redis.sadd(:schedules_changed, name)
    redis.sadd(:persisted_schedules, name) if persist
  end
  config
end