Skip to content

Instantly share code, notes, and snippets.

@betawaffle
Created November 20, 2013 19:53
Show Gist options
  • Save betawaffle/7569890 to your computer and use it in GitHub Desktop.
Save betawaffle/7569890 to your computer and use it in GitHub Desktop.
class BackoffTimer
class << self
def create(range, stepper, opts = {})
timer = new(intervals(range, stepper), opts[:immediate], opts[:callback] || Proc.new)
timer.start unless opts[:start] == false
timer
end
def exponential(range, opts = {})
opts[:callback] ||= Proc.new
base = opts[:base] || 2
create range, ->(x) { x * base }, opts
end
def linear(range, opts = {})
opts[:callback] ||= Proc.new
step = opts[:step] || 1
create range, ->(x) { x + step }, opts
end
private
def intervals(range, stepper)
return enum_for(:intervals, range, stepper) unless block_given?
value = range.min
begin
yield value
value = stepper.(value)
end while value < range.max
value = range.max
while true
yield value
end
binding.pry
end
def intervals(range, stepper)
Enumerator.new do |y|
value = range.min
begin
y << value
value = stepper.(value)
end while value < range.max
value = range.max
while true
y << value
end
binding.pry
end
end
end
def initialize(intervals, immediate = nil, proc = Proc.new)
@intervals = intervals.to_enum
@immediate = immediate.nil? ? true : immediate
@cancelled = nil
@proc = proc
@fire = method(:fire)
end
def cancel
@cancelled = true
self
end
def reset(immediate = false)
@intervals.rewind
@immediate = immediate
self
end
def start
unless @cancelled.nil?
warn "Timer already started! (#{self})"
return
end
@cancelled = false
schedule
self
end
private
def fire
return if @cancelled
@proc.(self)
schedule
end
def schedule
begin
interval = @immediate ? nil : @intervals.next
rescue StopIteration
@cancelled = true
else
if interval.nil?
EventMachine.next_tick(@fire)
else
EventMachine.add_timer(interval, @fire)
end
@immediate = false
end
end # schedule
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment