Class: PeriodicScheduler

Inherits:
Object
  • Object
show all
Defined in:
lib/periodic-scheduler.rb

Defined Under Namespace

Classes: EmptyScheduleError, Event, MissedScheduleError, RealTimeToQuantizedSpaceProjection

Instance Method Summary collapse

Constructor Details

#initialize(quantum = 5.0, options = {}) ⇒ PeriodicScheduler

Returns a new instance of PeriodicScheduler.



82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/periodic-scheduler.rb', line 82

def initialize(quantum = 5.0, options = {})
  time_source = (options[:time_source] or lambda {Time.now.to_f})
  wait_function = (options[:wait_function] or lambda{|t| sleep t})

  @quantized_space = RealTimeToQuantizedSpaceProjection.new(
    quantum,
    lambda {|v| v.ceil} # behave like sleep - never execute too early
  )
  @time_source = time_source
  @wait_function = wait_function

  @events = {}
end

Instance Method Details

#after(period, &callback) ⇒ Object



96
97
98
# File 'lib/periodic-scheduler.rb', line 96

def after(period, &callback)
	schedule_event Event.new(@quantized_space, real_now, period, false, &callback)
end

#empty?Boolean

Returns:

  • (Boolean)


156
157
158
# File 'lib/periodic-scheduler.rb', line 156

def empty?
@events.empty?
end

#every(period, &callback) ⇒ Object



100
101
102
# File 'lib/periodic-scheduler.rb', line 100

def every(period, &callback)
	schedule_event Event.new(@quantized_space, real_now, period, true, &callback)
end

#runObject

Raises:



113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
# File 'lib/periodic-scheduler.rb', line 113

def run
earliest_quant = @events.keys.sort.first
raise EmptyScheduleError, "no events scheduled" unless earliest_quant

  wait_time = @quantized_space.revers_project(earliest_quant) - real_now
wait_time = 0 if wait_time < 0
  wait(wait_time)

objects = []

  qnow = quantized_now

# move quants to be run away to separate array
  quants = @events.keys.select{|k| k <= qnow}.sort.map{|q| @events.delete(q)}

# we have missed one or more scheduled quants
if quants.length > 1
    begin
      # we raise it so it has proper backtrace
      raise MissedScheduleError.new("missed schedule by #{-wait_time} seconds")
    rescue StandardError => error
		yield error if block_given?
    end
  end

# Call callback for every quant and reschedule if needed
  quants.each do |events|
	# get all events for quantum that are not stopped
    events.each do |e|
      begin
        objects << e.call
      rescue StandardError => error
			# Yield errors to block
			yield error if block_given?
      end
      e.reschedule(quantized_now) if e.keep? and not e.stopped?
    end
  end

# return collected callabck return objects
objects
end

#run!(&block) ⇒ Object



104
105
106
107
108
109
110
111
# File 'lib/periodic-scheduler.rb', line 104

def run!(&block)
  begin
    loop do
      run(&block)
    end
  rescue EmptyScheduleError
  end
end