LoginSignup
0
0

More than 3 years have passed since last update.

Exponential Backoff ってなんじゃらホイ?を拡張してみた

Last updated at Posted at 2021-04-09

0. はじめに

今回の記事は Ruby 2.5.7 で動作確認しています 😗

1. 前回のモジュールを rescue 〜 retry で使ってみよう

前回の記事 Exponential Backoff ってなんじゃらホイ?を Enumerator クラスで書いてみた のコメント欄で、「リトライ処理は rescue 〜 retry を使うことが多い」というご意見をいただきましたので、前回作った ExponentialBackoff モジュールを、rescue 〜 retry のパターンに組み込むことを考えてみたいと思います。

とりあえず組込例は以下のような感じになります

def request_with_retry
  request                                         # リクエスト失敗時は例外エラーが発生
rescue => exception
  eb ||= ExponentialBackoff.call(max_attempt: 5)  # 5回分の値を返す Enumerator オブジェクトを生成 
  backoff = eb.next rescue nil                    # 次の値が取得できずに例外が発生した場合は、rescue して nil を代入
  sleep backoff and retry if backoff              # 次の値が取得できていれば、その値秒だけ sleep して retry
end

5 行目の eb.next で次の値を取り出すときに、max_attempt に達していたら StopIteration エラーが発生しますが、それを後置の rescue で捕捉して nil を返しています。例外エラーの発生ありきでリトライのフローが制御されており、なんとも微妙です :thinking:

そこで、リトライ上限に達したかどうかを判定できるメソッドを追加することにしました。

2. #peek? メソッドを追加しよう

追加するメソッドは、返却される Enumerator オブジェクトを拡張する形で実装することにします。

以下のように、リトライ上限に達したかどうかを boolean で返す、#peek? メソッドを備えた PeekQues モジュールを用意しました。

module PeekQues
  def peek?
    peek
    true
  rescue StopIteration
    false
  end
end

そして、ExponentialBackoff.call が Enumerator オブジェクトを返す際に、上記の PeekQues モジュールを extend します。

module ExponentialBackoff
  def self.call(max_attempt: Float::INFINITY, capacity: Float::INFINITY, base: 1)
    Enumerator
      .new(max_attempt) { |yielder|
        (1..max_attempt) { |attempt|
          yielder << [capacity, base * 2 ** attempt].min
        }
      }
      .extend(PeekQues) # 返却するオブジェクトに #peek? メソッドを追加
  end
end

3. 追加した #peek? メソッドを使ってみよう

それでは、追加した #peek? メソッドを利用して、冒頭のリトライ処理を改善してみます。

こんな感じになります。

def request_with_retry
  request                                         # リクエスト失敗時は例外エラーが発生
rescue => exception
  eb ||= ExponentialBackoff.call(max_attempt: 5)  # 5回分の値を返す Enumerator オブジェクトを生成
  sleep eb.next and retry if eb.peek?             # 次の値が取得できるなら、その値秒だけ sleep して retry
end

後置の rescue が消えていい感じになりました :smile:

4. おわりに

これで、リトライの制御フローに rescue を利用する必要がなくなり、ExponentialBackoff モジュールがより使いやすくなりました :clap:

みなさんもぜひ使ってみてくださいね :kissing_heart:

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