LoginSignup
3
3

More than 5 years have passed since last update.

retryable gemで、「retryがすべて失敗した」ときの処理を書く

Posted at

Retryable

retry_count = 0;
tries = 3;
begin
  do_something
rescue => e
  retry_count += 1;
  raise e if retry > tries;
  sleep 1
  retry
end

これが、

Retryable.retry(:tries => 3) { do_something }

と書ける

n回失敗したらログを書いて終了

retry_count = 0;
tries = 3;
begin
  do_something
rescue => e
  retry_count += 1;
  if retry > tries
    log("die")
    exit 1
  end
  sleep 1
  retry
end

Retryableのオプションには、rescue節の中の処理を書くexception_cbコールバックと、ensure節の処理を書くensureコールバックがある。このうちensureコールバックを使う。

Retryable.retry(:tries => n, :ensure => Proc.new {|tries| ...}) {...}

引数だけではn回目に成功した場合とn回失敗した場合の区別がつかない。が、$!に例外が設定されているかどうかで区別できる

ensure_cb = Proc.new do |tries|
  if $!
    log("die")
    exit 1
  end
end

ただし、コールバックの実行が終わったら例外が発生するので、exitする場合でないと使えない。

別案

#案1
#一回多く実行させてそれを拾う。:tries => n + 1に注意
Retryable.retry(:tries => n + 1) do |tries, exception|
  if(:tries >= n)
    log("die")
    exit
  end
  do_something
end

#案2
#最終回失敗したら例外が出るのでbeginで拾う
begin
  Retryable.retry(:tries => n) { do_something }
rescue
  log("die")
  exit
end

どれもいまいちすっきりしない。

最終回の試行が失敗した後に呼ばれるfinallyコールバックと、例外を送出しないオプションを追加するPRを出してる人はいるのだけどマージされていない。

3
3
0

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
3
3