Skip to content

Instantly share code, notes, and snippets.

@fornellas
Created August 23, 2016 16:54
Show Gist options
  • Save fornellas/e71b69e964056f204e09773f1b2f150c to your computer and use it in GitHub Desktop.
Save fornellas/e71b69e964056f204e09773f1b2f150c to your computer and use it in GitHub Desktop.
Retry Proxy
class RetryProxy < BasicObject
def initialize target, retries, logger=nil
@target = target
@retries = retries
@logger = logger
end
BasicObject.instance_methods.each do |basic_object_instance_method|
define_method(basic_object_instance_method) do |*args, &block|
@target.send(basic_object_instance_method, *args, &block)
end
end
def method_missing symbol, *args, &block
retries = @retries
begin
@target.send(symbol, *args, &block)
rescue
retries -= 1
::Kernel.raise $! if retries == 0
message = "While calling #{@target.to_s} (#{@target.class}) received exception, will retry: #{$!} (#{$!.class})"
@logger.warn(message) if @logger
retry
end
end
end
class FailOnce
def initialize
@fail = true
end
def fail
if @fail
@fail = false
raise "Fail at first!"
else
"Now it works!"
end
end
def == other
true
end
end
require 'logger'
target = FailOnce.new
proxy_target = RetryProxy.new(target, 3, Logger.new(STDOUT))
p(proxy_target.fail)
# BasicObject instance methods are also delegated
p(proxy_target == 3)
# >> W, [2016-08-23T13:54:37.259614 #25557] WARN -- : While calling #<FailOnce:0x007fcfe39d5778> (FailOnce) received exception, will retry: Fail at first! (RuntimeError)
# >> "Now it works!"
# >> true
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment