class Tickwork::Manager
Constants
- MANAGER_KEY
Attributes
config[R]
Public Class Methods
new()
click to toggle source
# File lib/tickwork/manager.rb, line 11 def initialize @events = [] @callbacks = {} @config = default_configuration @handler = nil @error_handler = nil end
Public Instance Methods
clear!()
click to toggle source
# File lib/tickwork/manager.rb, line 134 def clear! data_store.write(data_store_key, nil) end
configure() { |config| ... }
click to toggle source
# File lib/tickwork/manager.rb, line 23 def configure yield(config) [:max_threads, :tick_size, :max_ticks, :max_catchup].each do |int_config_key| config[int_config_key] = config[int_config_key].to_i end if config[:sleep_timeout] config[:logger].warn 'INCORRECT USAGE: sleep_timeout is not used' if config[:sleep_timeout] < 1 config[:logger].warn 'sleep_timeout must be >= 1 second' end end if config[:data_store].nil? raise NoDataStoreDefined.new end if config[:tick_size] > 60 config[:logger].warn 'tick_size is greater than 60. Events scheduled for a specific time may be missed' end end
data_store()
click to toggle source
# File lib/tickwork/manager.rb, line 65 def data_store config[:data_store] end
data_store_key()
click to toggle source
# File lib/tickwork/manager.rb, line 89 def data_store_key @data_store_key ||= config[:namespace] + MANAGER_KEY end
default_configuration()
click to toggle source
# File lib/tickwork/manager.rb, line 42 def default_configuration { logger: Logger.new(STDOUT), thread: false, max_threads: 10, namespace: '_tickwork_', tick_size: 60, # 1 minute max_ticks: 10, max_catchup: 3600 # 1 hour } end
error_handler(&block)
click to toggle source
# File lib/tickwork/manager.rb, line 60 def error_handler(&block) @error_handler = block if block_given? @error_handler end
every(period, job, options={}, &block)
click to toggle source
# File lib/tickwork/manager.rb, line 74 def every(period, job, options={}, &block) if period < config[:tick_size] config[:logger].warn 'period is smaller than tick size. will fail to schedule all events' end if options[:at].respond_to?(:each) every_with_multiple_times(period, job, options, &block) else register(period, job, block, options) end end
fire_callbacks(event, *args)
click to toggle source
# File lib/tickwork/manager.rb, line 85 def fire_callbacks(event, *args) @callbacks[event].nil? || @callbacks[event].all? { |h| h.call(*args) } end
handle_error(e)
click to toggle source
# File lib/tickwork/manager.rb, line 142 def handle_error(e) error_handler.call(e) if error_handler end
handler(&block)
click to toggle source
# File lib/tickwork/manager.rb, line 54 def handler(&block) @handler = block if block_given? raise NoHandlerDefined unless @handler @handler end
log(msg)
click to toggle source
# File lib/tickwork/manager.rb, line 146 def log(msg) config[:logger].info(msg) end
log_error(e)
click to toggle source
# File lib/tickwork/manager.rb, line 138 def log_error(e) config[:logger].error(e) end
on(event, options={}, &block)
click to toggle source
# File lib/tickwork/manager.rb, line 69 def on(event, options={}, &block) raise "Unsupported callback #{event}" unless [:before_tick, :after_tick, :before_run, :after_run].include?(event.to_sym) (@callbacks[event.to_sym]||=[]) << block end
run()
click to toggle source
pretty straight forward if you think about it run the ticks from the last time we ran to our max but don't run ticks in the future
# File lib/tickwork/manager.rb, line 96 def run raise NoDataStoreDefined.new if data_store.nil? log "Starting clock for #{@events.size} events: [ #{@events.map(&:to_s).join(' ')} ]" last = last_t = data_store.read(data_store_key) last ||= Time.now.to_i - config[:tick_size] if !config[:max_catchup].nil? && config[:max_catchup] > 0 && last < Time.now.to_i - config[:max_catchup] last = Time.now.to_i - config[:max_catchup] - config[:tick_size] end ticks = 0 tick_time = last + config[:tick_size] while ticks < config[:max_ticks] && tick_time <= Time.now.to_i do tick(tick_time) last = tick_time tick_time += config[:tick_size] ticks += 1 end data_store.write(data_store_key, last) last end
thread_available?()
click to toggle source
# File lib/tickwork/manager.rb, line 19 def thread_available? Thread.list.select { |t| t['creator'] == self }.count < config[:max_threads] end
tick(t=Time.now.to_i)
click to toggle source
# File lib/tickwork/manager.rb, line 119 def tick(t=Time.now.to_i) t = Time.at(t) # TODO refactor below if (fire_callbacks(:before_tick)) events = events_to_run(t) events.each do |event| if (fire_callbacks(:before_run, event, t)) event.run(t) fire_callbacks(:after_run, event, t) end end end fire_callbacks(:after_tick) events end
Private Instance Methods
events_to_run(t)
click to toggle source
# File lib/tickwork/manager.rb, line 151 def events_to_run(t) @events.select{ |event| event.run_now?(t) } end
every_with_multiple_times(period, job, options={}, &block)
click to toggle source
# File lib/tickwork/manager.rb, line 169 def every_with_multiple_times(period, job, options={}, &block) each_options = options.clone options[:at].each do |at| each_options[:at] = at register(period, job + '_' + at, block, each_options) end end
guard_duplicate_events(event)
click to toggle source
# File lib/tickwork/manager.rb, line 163 def guard_duplicate_events(event) if @events.map{|e| e.to_s }.include? event.to_s raise DuplicateJobName end end
register(period, job, block, options)
click to toggle source
# File lib/tickwork/manager.rb, line 155 def register(period, job, block, options) options.merge({:namespace => config[:namespace]}) event = Event.new(self, period, job, block || handler, options) guard_duplicate_events(event) @events << event event end