lib/clockwork.rb in clockwork-0.3.2 vs lib/clockwork.rb in clockwork-0.3.3

- old
+ new

@@ -1,145 +1,177 @@ module Clockwork - class FailedToParse < StandardError; end; - @@events = [] + @@events = [] - class Event - attr_accessor :job, :last + class At + class FailedToParse < StandardError; end; + NOT_SPECIFIED = class << nil + include Comparable + def <=>(other); 0; end # equals to anything + end + WDAYS = %w[sunday monday tuesday wednesday thursday friday saturday].map do |w| + [w, w.capitalize, w[0...3], w[0...3].capitalize] + end - def initialize(period, job, block, options={}) - @period = period - @job = job - @at = parse_at(options[:at]) - @last = nil - @block = block - end + def self.parse(at) + return unless at + case at + when /^([[:alpha:]]+)\s(.*)$/ + ret = parse($2) + wday = WDAYS.find_index {|x| x.include?($1) } + raise FailedToParse, at if wday.nil? + ret.wday = wday + ret + when /^(\d{1,2}):(\d\d)$/ + new($2.to_i, $1.to_i) + when /^\*{1,2}:(\d\d)$/ + new($1.to_i) + else + raise FailedToParse, at + end + rescue ArgumentError + raise FailedToParse, at + end - def to_s - @job - end + attr_writer :min, :hour, :wday - def time?(t) - ellapsed_ready = (@last.nil? or (t - @last).to_i >= @period) - time_ready = (@at.nil? or ((@at[0].nil? or t.hour == @at[0]) and t.min == @at[1])) - ellapsed_ready and time_ready - end + def initialize(min, hour=NOT_SPECIFIED, wday=NOT_SPECIFIED) + if min.nil? || min < 0 || min > 59 || + hour < 0 || hour > 23 || + wday < 0 || wday > 6 + raise ArgumentError + end + @min = min + @hour = hour + @wday = wday + end - def run(t) - @last = t - @block.call(@job) - rescue => e - log_error(e) - end + def ready?(t) + t.min == @min and t.hour == @hour and t.wday == @wday + end + end - def log_error(e) - STDERR.puts exception_message(e) - end + class Event + attr_accessor :job, :last - def exception_message(e) - msg = [ "Exception #{e.class} -> #{e.message}" ] + def initialize(period, job, block, options={}) + @period = period + @job = job + @at = At.parse(options[:at]) + @last = nil + @block = block + end - base = File.expand_path(Dir.pwd) + '/' - e.backtrace.each do |t| - msg << " #{File.expand_path(t).gsub(/#{base}/, '')}" - end + def to_s + @job + end - msg.join("\n") - end + def time?(t) + ellapsed_ready = (@last.nil? or (t - @last).to_i >= @period) + ellapsed_ready and (@at.nil? or @at.ready?(t)) + end - def parse_at(at) - return unless at - case at - when /^(\d{1,2}):(\d\d)$/ - hour = $1.to_i - min = $2.to_i - raise FailedToParse, at if hour >= 24 || min >= 60 - [hour, min] - when /^\*{1,2}:(\d\d)$/ - min = $1.to_i - raise FailedToParse, at if min >= 60 - [nil, min] - else - raise FailedToParse, at - end - end - end + def run(t) + @last = t + @block.call(@job) + rescue => e + log_error(e) + end - extend self + def log_error(e) + STDERR.puts exception_message(e) + end - def handler(&block) - @@handler = block - end + def exception_message(e) + msg = [ "Exception #{e.class} -> #{e.message}" ] - class NoHandlerDefined < RuntimeError; end + base = File.expand_path(Dir.pwd) + '/' + e.backtrace.each do |t| + msg << " #{File.expand_path(t).gsub(/#{base}/, '')}" + end - def get_handler - raise NoHandlerDefined unless (defined?(@@handler) and @@handler) - @@handler - end + msg.join("\n") + end + end - def every(period, job, options={}, &block) - if options[:at].respond_to?(:each) - each_options = options.clone - options[:at].each do |at| - each_options[:at] = at - register(period, job, block, each_options) - end - else - register(period, job, block, options) - end - end + extend self - def run - log "Starting clock for #{@@events.size} events: [ " + @@events.map { |e| e.to_s }.join(' ') + " ]" - loop do - tick - sleep 1 - end - end + def handler(&block) + @@handler = block + end - def log(msg) - puts msg - end + class NoHandlerDefined < RuntimeError; end - def tick(t=Time.now) - to_run = @@events.select do |event| - event.time?(t) - end + def get_handler + raise NoHandlerDefined unless (defined?(@@handler) and @@handler) + @@handler + end - to_run.each do |event| - log "Triggering #{event}" - event.run(t) - end + def every(period, job, options={}, &block) + if options[:at].respond_to?(:each) + each_options = options.clone + options[:at].each do |at| + each_options[:at] = at + register(period, job, block, each_options) + end + else + register(period, job, block, options) + end + end - to_run - end + def run + log "Starting clock for #{@@events.size} events: [ " + @@events.map { |e| e.to_s }.join(' ') + " ]" + loop do + tick + sleep 1 + end + end - def clear! - @@events = [] - @@handler = nil - end + def log(msg) + puts msg + end - private - def register(period, job, block, options) - event = Event.new(period, job, block || get_handler, options) - @@events << event - event - end - + def tick(t=Time.now) + to_run = @@events.select do |event| + event.time?(t) + end + + to_run.each do |event| + log "Triggering #{event}" + event.run(t) + end + + to_run + end + + def clear! + @@events = [] + @@handler = nil + end + + private + def register(period, job, block, options) + event = Event.new(period, job, block || get_handler, options) + @@events << event + event + end + end -unless 1.respond_to?(:seconds) +unless 1.respond_to?(:seconds) class Numeric - def seconds; self; end - alias :second :seconds + def seconds; self; end + alias :second :seconds - def minutes; self * 60; end - alias :minute :minutes + def minutes; self * 60; end + alias :minute :minutes - def hours; self * 3600; end - alias :hour :hours + def hours; self * 3600; end + alias :hour :hours - def days; self * 86400; end - alias :day :days + def days; self * 86400; end + alias :day :days + + def weeks; self * 604800; end + alias :week :weeks end end