Skip to content

Instantly share code, notes, and snippets.

@0x000def42
Created January 17, 2023 08:10
Show Gist options
  • Select an option

  • Save 0x000def42/58ebf13f55d9fdbeccca48c7d14b18a3 to your computer and use it in GitHub Desktop.

Select an option

Save 0x000def42/58ebf13f55d9fdbeccca48c7d14b18a3 to your computer and use it in GitHub Desktop.
# frozen_string_literal: true
# == Examples of usage
# class A
# include WithRetry
#
# def process
# with_retry(catch_only_on_expections: [StandardError]) do
# # do something
# end
# end
# end
#
# class B
# include WithRetry
# def process
# with_retry(**retry_options) do
# # do something like 'raise RuntimeError'
# end
# end
#
# private
#
# def retry_options
# {
# catch_only_on_expections: [RuntimeError, ArgumentError],
# strategy: FibonacciRetry.build,
# max_retries: 10,
# catch_callback: proc do |e|
# puts "Attempts are over :("
# end
# }
# end
# end
#
module WithRetry
def with_retry(**opts)
policy = Policy.new(**opts)
retries = 0
begin
yield
rescue *policy.only_on_exceptions => e
return policy.catch_callback.call(e) if retries >= policy.max_retries
sleep policy.strategy.next
retries += 1
retry
end
end
class Policy
extend Dry::Initializer
option :only_on_exceptions
option :catch_callback, default: proc { proc { |e| raise e } }
option :max_retries, default: proc { 3 }
option :strategy, default: proc { FastRetry.build }
end
#
# == Retries
# Note: You may implement another custom retrier
# Each iteration will sleep fixed time (default: 0 seconds)
module FastRetry
def self.build(value: 0)
Enumerator.new do |sleep_time|
loop { sleep_time << value }
end
end
end
# Each iteration will sleep next fibonacci value
module FibonacciRetry
def self.build
Enumerator.new do |sleep_time|
next_time = prev_time = 1
loop do
sleep_time << next_time
next_time, prev_time = next_time + prev_time, next_time
end
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment