lib/clockwork.rb in clockwork-0.5.5 vs lib/clockwork.rb in clockwork-0.6.0

- old
+ new

@@ -1,216 +1,35 @@ require 'logger' require 'active_support/time' +require 'clockwork/at' +require 'clockwork/event' +require 'clockwork/manager' + module Clockwork + extend self - @@events = [] + @@manager = Manager.new - class At - class FailedToParse < StandardError; end; - NOT_SPECIFIED = nil - WDAYS = %w[sunday monday tuesday wednesday thursday friday saturday].map do |w| - [w, w.capitalize, w[0...3], w[0...3].capitalize] - 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 - - attr_writer :min, :hour, :wday - - def initialize(min, hour=NOT_SPECIFIED, wday=NOT_SPECIFIED) - if min.nil? || min < 0 || min > 59 || - (hour != NOT_SPECIFIED && (hour < 0 || hour > 23)) || - (wday != NOT_SPECIFIED && (wday < 0 || wday > 6)) - raise ArgumentError - end - @min = min - @hour = hour - @wday = wday - end - - def ready?(t) - t.min == @min and - (@hour == NOT_SPECIFIED or t.hour == @hour) and - (@wday == NOT_SPECIFIED or t.wday == @wday) - end + def configure(&block) + @@manager.configure(&block) end - class Event - attr_accessor :job, :last - - def initialize(period, job, block, options={}) - @period = period - @job = job - @at = At.parse(options[:at]) - @last = nil - @block = block - if options[:if] - if options[:if].respond_to?(:call) - @if = options[:if] - else - raise ArgumentError.new(':if expects a callable object, but #{options[:if]} does not respond to call') - end - end - - @thread = !!(options.has_key?(:thread) ? options[:thread] : Clockwork.config[:thread]) - - @timezone = options[:tz] || Clockwork.config[:tz] - end - - def to_s - @job - end - - def convert_timezone(t) - @timezone ? t.in_time_zone(@timezone) : t - end - - def time?(t) - t = convert_timezone(t) - elapsed_ready = (@last.nil? or (t - @last).to_i >= @period) - elapsed_ready and (@at.nil? or @at.ready?(t)) and (@if.nil? or @if.call(t)) - end - - def thread? - @thread - end - - def run(t) - t = convert_timezone(t) - @last = t - - if thread? - if Clockwork.thread_available? - Thread.new { execute } - else - log_error "Threads exhausted; skipping #{self}" - end - else - execute - end - end - - def execute - @block.call(@job) - rescue => e - log_error e - end - - def log_error(e) - Clockwork.config[:logger].error(e) - end - - def exception_message(e) - msg = [ "Exception #{e.class} -> #{e.message}" ] - - base = File.expand_path(Dir.pwd) + '/' - e.backtrace.each do |t| - msg << " #{File.expand_path(t).gsub(/#{base}/, '')}" - end - - msg.join("\n") - end - end - - def thread_available? - Thread.list.count < config[:max_threads] - end - - def configure - yield(config) - end - - def config - @@configuration - end - - extend self - - def default_configuration - { :sleep_timeout => 1, :logger => Logger.new(STDOUT), :thread => false, :max_threads => 10 } - end - - @@configuration = default_configuration - def handler(&block) - @@handler = block + @@manager.handler(&block) end - class NoHandlerDefined < RuntimeError; end - - def get_handler - raise NoHandlerDefined unless (defined?(@@handler) and @@handler) - @@handler - 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 + @@manager.every(period, job, options, &block) end def run - log "Starting clock for #{@@events.size} events: [ " + @@events.map { |e| e.to_s }.join(' ') + " ]" - loop do - tick - sleep(config[:sleep_timeout]) - end + @@manager.run end - def log(msg) - config[:logger].info(msg) - 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 - @@configuration = Clockwork.default_configuration + @@manager = Manager.new 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) class Numeric def seconds; self; end