Created
October 24, 2012 00:58
-
-
Save cheald/3943062 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'rufus/scheduler' | |
class CronManager | |
def self.schedule(redis, &block) | |
@singleton ||= new(redis, &block) | |
end | |
def every(timing, options = {}, &block) | |
# In order to make sure that jobs are executed at the same time regardless of who runs them | |
# we quantitize the start time to the next-nearest time slice. This more closely emulates | |
# cron-style behavior. | |
# | |
# This does assume that your system dates are in sync. | |
seconds = Rufus.parse_duration_string(timing) | |
now = Time.now.to_i | |
start_at = Time.at( now + (seconds - (now % seconds)) ) | |
options = options.merge(:first_at => start_at) | |
schedule :every, timing, options, &block | |
end | |
def cron(timing, options = {}, &block) | |
schedule :cron, timing, options, &block | |
end | |
private | |
def schedule(method, timing, options, &block) | |
name = options.delete :name | |
key = "cron:%s-%s" % [timing, name || Digest::SHA1.hexdigest(block.to_ruby)] | |
@scheduler.send method, timing, options do | |
# If we can acquire a lock... | |
if @redis.setnx key | |
# ...set the lock to expire in 95% of the duration's time, to account for system time drift | |
@redis.expire key, (seconds * 0.95).floor | |
# ...and then run the job | |
block.call | |
end | |
end | |
end | |
def initialize(redis, &block) | |
@redis = redis | |
@scheduler = Rufus::Scheduler.start_new | |
instance_eval &block | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment