Skip to content

Instantly share code, notes, and snippets.

@jamesgecko
Created June 25, 2015 01:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jamesgecko/9f060a2e0f2a333630f0 to your computer and use it in GitHub Desktop.
Save jamesgecko/9f060a2e0f2a333630f0 to your computer and use it in GitHub Desktop.
class Configuration
def self.geocoder_service_fallback_order
[:bing, :google]
end
def self.geocoder_default_api
:bing
end
end
class Logger
def self.warn(string)
puts string
end
end
class Rails
def self.configuration
Configuration
end
def self.logger
Logger
end
end
class Geocoder
def self.configure(options)
puts "Geocoder reconfigured: #{options}"
end
end
class Geocoder::ServiceUnavailable < Exception; end
class Geocoder::OverQueryLimitError < Exception; end
class SafeGeocoder
# Public: Takes a block containing a Geocoder method and retries it against
# fallback services if the block throws Geocoder::ServiceUnavailable
def self.wrap(&block)
Rails.configuration.geocoder_service_fallback_order.each do |service|
Geocoder.configure(lookup: service)
begin
return block.call
rescue Geocoder::ServiceUnavailable, Geocoder::OverQueryLimitError => e
Rails.logger.warn "#{service} geocoder failed #{e.to_s}"
next
end
break
end
ensure
Geocoder.configure(lookup: Rails.configuration.geocoder_default_api)
end
end
puts '--- Success ---'
puts SafeGeocoder.wrap {
"I'm a winner!"
}.inspect
puts
puts '--- Failure ---'
puts SafeGeocoder.wrap {
raise Geocoder::ServiceUnavailable
}.inspect
><((°> ruby temp.rb
--- Success ---
Geocoder reconfigured: {:lookup=>:bing}
Geocoder reconfigured: {:lookup=>:bing}
"I'm a winner!"
--- Failure ---
Geocoder reconfigured: {:lookup=>:bing}
bing geocoder failed Geocoder::ServiceUnavailable
Geocoder reconfigured: {:lookup=>:google}
google geocoder failed Geocoder::ServiceUnavailable
Geocoder reconfigured: {:lookup=>:bing}
[:bing, :google]
@jamesgecko
Copy link
Author

Minimal version:

def fallback(&block)
  fallbacks = [:foo, :bar]
  fallbacks.each do |item|
    begin
      return block.call
    rescue
      puts "There was an error. Try next fallback"
      next
    end
    break
  end
end

puts fallback {
  "I'm a winner!"
}.inspect
puts '--'
puts fallback {
  raise 'Oops'
}.inspect

Output:

"I'm a winner!"
--
There was an error. Try next fallback
There was an error. Try next fallback
[:foo, :bar]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment