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