制御構文の retry
を使うことで記述できます。
def retry_on_error(times: 3)
try = 0
begin
try += 1
yield
rescue
retry if try < times
raise
end
end
retry_on_error { do_something }
間違った例 or 無限リトライ
下のように記述すると、 try
ローカル変数が毎回 0
を代入されるため、無限リトライになってしまいます。
def retry_on_error(times: 3)
try = 0
yield
rescue
try += 1
retry if try < times
raise
end
無限リトライを記述するなら、下でよいです。
def retry_on_error
yield
rescue
retry
end
しかし、これは呼び出し元で記述した方がわかりやすいかもしれません。
retryable を使う
スリープを挟みたい、特定のエラーでのみリトライしたいなど、より複雑な制御をしたくなったときは、gem の retryable を使うとよいかもしれません。
Retryable.retryable do
# do something
end
これだけで、 StandardError
を捕捉して 1 秒の sleep を挟みつつ、2回までリトライしてくれます。
呼び出し時のオプションや Retryable.configure { |c| ... }
で、細かなカスタマイズを行うことができます。
ピュア Ruby で書かれており、依存 gem もなく古いバージョンの Ruby でも動作するので、自前で複雑な制御を実装するよりは筋が良さそうです。