Created
January 17, 2023 08:10
-
-
Save 0x000def42/58ebf13f55d9fdbeccca48c7d14b18a3 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # 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