LoginSignup
14
10

More than 5 years have passed since last update.

Rubyでn回まではリトライして処理して欲しい時

Posted at

たまにないですか?
3回ぐらいはとりあえずリトライして、その後はエラーとするか〜みたいな事。
そんな時どう書くのが良いのかな〜と。

というわけで、試しに書いてみました。

コード

module_retry.rb
module Retry
  DEFAULT_RETRY_LIMIT = 3

  # retry_limit以下の回数分yieldする.
  # 指定が無い場合は、DEFAULT_RETRY_LIMIT回以下
  def challenge(options = {})
    raise ArgumentError.new "give block" unless block_given?

    begin
      count = count.to_i + 1
      yield(count)
    rescue => e
      limit ||= (options[:retry_limit] || DEFAULT_RETRY_LIMIT)
      if (count < limit)
        retry
      else
        puts "over retry limit #{limit}."
        raise
      end
    end
  end

  # includeしなくても、モジュールメソッドとしても呼び出したい時用
  extend self
end

if __FILE__ == $0
  def hoge
    puts "hoge"
    raise "raise error test1."
  end

  puts "test1:モジュールメソッドとして呼び出し"
  Retry.challenge(retry_limit: 2){|times|
    hoge
  } rescue nil # エラーで停まらないように

  include Retry
  begin
    puts "\ntest2:includeして呼び出し"
    challenge{|times|
      puts times
      raise "raise error test2."
    }
  rescue => e
    puts "#<#{e.class}: #{e.message}>"
    puts "  #{e.backtrace.join("\n  ")}"
  end
end

後は、このファイルをrequireすれば目標達成ですね。

実行結果

$ ruby module_retry.rb 
test1:モジュールメソッドとして呼び出し
hoge
hoge
over retry limit 2.

test2:includeして呼び出し
1
2
3
over retry limit 3.
#<RuntimeError: raise error test2.>
  module_retry.rb:42:in `block in <main>'
  module_retry.rb:10:in `challenge'
  module_retry.rb:40:in `<main>'

backtraceに余分なモノが挟まってしまうのが気になりますね。
他に良い書き方があるような気がします(=w=;

14
10
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
10