Methods I like to monkey-patch onto the Object class in Ruby
# Say you want to look up the attrs of a Stripe Event for logging to your internal database. | |
attrs = begin | |
retriable(Stripe::APIConnectionError, Stripe::APIError, max: 25) do | |
# ... retrieve attrs from the Stripe event here... | |
end | |
rescue Stripe::APIConnectionError, Stripe::APIError | |
# We're inside an SQS queue block | |
throw :skip_delete # we'll just have to wait on this event, come back later | |
rescue Stripe::Error | |
notify $! | |
next # something's off, maybe hackery? just skip this event | |
end | |
class Object | |
# Always throw errors in development and test, they're too easy to miss in the logs, | |
# and we should be "safely" handling these things, not swallowing them | |
# In production, swallowing errors makes for a much richer experience | |
def notify(error) | |
raise error unless Rails.env.production? | |
Airbrake.notify(error) | |
end | |
# If a 3rd-party service is down, like Stripe or AWS, | |
# we might want to just retry it again after a bit of a wait | |
# | |
# Note rack-timeout is set to 1 second, but hopefully we're only ever | |
# talking to 3rd-party APIs in background jobs, eh? ;-) | |
def retriable(*errors, &block) | |
options = errors.extract_options! # rails-ism: if you're using this elsewhere, adjust accordingly | |
attempts = 0 # how many times have we tried this already? | |
max = options.delete(:max) || 0 | |
begin | |
yield | |
rescue *errors | |
Airbrake.notify $! | |
attempts += 1 | |
attempts > max and raise | |
sleep 1.15 ** attempts and retry | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment