2014-01-30 13:21:38 +08:00
|
|
|
module Scheduler
|
|
|
|
class ScheduleInfo
|
|
|
|
attr_accessor :next_run,
|
|
|
|
:prev_run,
|
|
|
|
:prev_duration,
|
2014-02-12 10:32:34 +08:00
|
|
|
:prev_result,
|
|
|
|
:current_owner
|
2014-01-30 13:21:38 +08:00
|
|
|
|
|
|
|
def initialize(klass, manager)
|
|
|
|
@klass = klass
|
|
|
|
@manager = manager
|
|
|
|
|
|
|
|
data = nil
|
|
|
|
|
|
|
|
if data = $redis.get(key)
|
|
|
|
data = JSON.parse(data)
|
|
|
|
end
|
|
|
|
|
|
|
|
if data
|
|
|
|
@next_run = data["next_run"]
|
|
|
|
@prev_run = data["prev_run"]
|
|
|
|
@prev_result = data["prev_result"]
|
|
|
|
@prev_duration = data["prev_duration"]
|
2014-02-12 10:32:34 +08:00
|
|
|
@current_owner = data["current_owner"]
|
2014-01-30 13:21:38 +08:00
|
|
|
end
|
|
|
|
rescue
|
|
|
|
# corrupt redis
|
2014-02-12 10:32:34 +08:00
|
|
|
@next_run = @prev_run = @prev_result = @prev_duration = @current_owner = nil
|
2014-01-30 13:21:38 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
def valid?
|
|
|
|
return false unless @next_run
|
2014-03-15 01:02:21 +08:00
|
|
|
(!@prev_run && @next_run < Time.now.to_i + 5.minutes) || valid_every? || valid_daily?
|
|
|
|
end
|
|
|
|
|
|
|
|
def valid_every?
|
|
|
|
return false unless @klass.every
|
2014-09-25 23:44:48 +08:00
|
|
|
!!@prev_run &&
|
2014-01-30 13:21:38 +08:00
|
|
|
@prev_run <= Time.now.to_i &&
|
|
|
|
@next_run < @prev_run + @klass.every * (1 + @manager.random_ratio)
|
|
|
|
end
|
|
|
|
|
2014-03-15 01:02:21 +08:00
|
|
|
def valid_daily?
|
|
|
|
return false unless @klass.daily
|
2014-09-25 23:44:48 +08:00
|
|
|
!!@prev_run &&
|
|
|
|
@prev_run <= Time.now.to_i &&
|
|
|
|
@next_run < @prev_run + 1.day
|
2014-03-15 01:02:21 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
def schedule_every!
|
2014-01-30 13:21:38 +08:00
|
|
|
if !valid? && @prev_run
|
|
|
|
mixup = @klass.every * @manager.random_ratio
|
|
|
|
mixup = (mixup * Random.rand - mixup / 2).to_i
|
|
|
|
@next_run = @prev_run + mixup + @klass.every
|
|
|
|
end
|
|
|
|
|
|
|
|
if !valid?
|
|
|
|
@next_run = Time.now.to_i + 5.minutes * Random.rand
|
|
|
|
end
|
2014-03-15 01:02:21 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
def schedule_daily!
|
|
|
|
return if valid?
|
|
|
|
|
|
|
|
at = @klass.daily[:at] || 0
|
|
|
|
today_begin = Time.now.midnight.to_i
|
|
|
|
today_offset = DateTime.now.seconds_since_midnight
|
|
|
|
|
|
|
|
# If it's later today
|
|
|
|
if at > today_offset
|
|
|
|
@next_run = today_begin + at
|
|
|
|
else
|
|
|
|
# Otherwise do it tomorrow
|
|
|
|
@next_run = today_begin + 1.day + at
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def schedule!
|
|
|
|
if @klass.every
|
|
|
|
schedule_every!
|
|
|
|
elsif @klass.daily
|
|
|
|
schedule_daily!
|
|
|
|
end
|
2014-01-30 13:21:38 +08:00
|
|
|
|
|
|
|
write!
|
|
|
|
end
|
|
|
|
|
|
|
|
def write!
|
|
|
|
clear!
|
|
|
|
redis.set key, {
|
|
|
|
next_run: @next_run,
|
|
|
|
prev_run: @prev_run,
|
|
|
|
prev_duration: @prev_duration,
|
2014-02-12 10:32:34 +08:00
|
|
|
prev_result: @prev_result,
|
|
|
|
current_owner: @current_owner
|
2014-01-30 13:21:38 +08:00
|
|
|
}.to_json
|
2014-04-17 13:57:17 +08:00
|
|
|
|
2014-01-30 13:21:38 +08:00
|
|
|
redis.zadd Manager.queue_key, @next_run , @klass
|
|
|
|
end
|
|
|
|
|
|
|
|
def del!
|
|
|
|
clear!
|
2014-02-12 10:32:34 +08:00
|
|
|
@next_run = @prev_run = @prev_result = @prev_duration = @current_owner = nil
|
2014-01-30 13:21:38 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
def key
|
|
|
|
Manager.schedule_key(@klass)
|
|
|
|
end
|
|
|
|
|
|
|
|
def redis
|
|
|
|
@manager.redis
|
|
|
|
end
|
|
|
|
|
|
|
|
private
|
|
|
|
def clear!
|
|
|
|
redis.del key
|
2014-04-17 13:57:17 +08:00
|
|
|
redis.zrem Manager.queue_key, @klass
|
2014-01-30 13:21:38 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
end
|