10
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

API呼び出しの回数制限にブチ当たった時のリトライ処理について

Posted at

はじめに

Google Sheets APIなどは、一定時間あたりのAPI実行回数に制限があって、
ちょっとした処理でもすぐにその制限を超えてしまうことがあります。
そんな場面で使えるRubyによる再処理についてお伝えしたいと思います。

この記事ではGoogle Sheets APIの使い方については説明いたしませんので、
Google Sheets APIの詳しい使い方を知りたい場合は他の記事をご参照ください。

Google Sheets API ついて

Googleドライブ上のスプレッドシートを操作するためのGoogleが提供しているAPIです。
スプレッドシートのセルの値を読み取ったり、セルに値を書き込んだりすることができます。

RubyからはGoogle公式のGemを使うと便利に操作することができます。
https://github.com/googleapis/google-api-ruby-client

gem 'google-api-client'

Google Sheets APIの回数制限について

Google Sheets APIは、下記URLページに記載されているように、API呼び出しに回数制限が設けられています。
https://developers.google.com/sheets/api/limits

スクリーンショット 2022-09-10 9.42.33.png
Googleに対して割り当ての増加リクエストを行うことができますが、トラフィック量が多いと料金が発生する可能性があるようです。

Google Sheets APIの例外

Google Sheets APIを短時間に集中して実行すると

「Quota exceeded … 」といった例外が発生することがあります。

前掲の表に記載されている制限を超えた場合に発生する例外です。
1分間、時間を空けて再度APIを実行すると今度はエラーが発生せずにAPIを実行できます。

Rubyによる再処理の方法

  1. 「begin rescue retry」で記述する
  2. メソッドやクラスに切り出す
  3. Gemを使う(Retryable)

1.「begin rescue retry」で記述する

サンプルコード


SLEEP_SEC = 60
MAX_RETRY = 3

retry_count = 0

begin

  # Google Sheets API の呼び出し処理

rescue => e
  if retry_count >= MAX_RETRY
    # リトライ回数オーバー
    raise e
  end
  retry_count += 1
  # リトライ待機中
  sleep SLEEP_SEC
  retry
end

(すべての例外をrescueしているのは目をつむってもらうとして)

Google Sheets API の呼び出し処理(1)

他の処理(1)

Google Sheets API の呼び出し処理(2)

他の処理(2)

Google Sheets API の呼び出し処理(3)

他の処理(3)

といったAPI呼び出しを行っている場合、そのまま再処理を記述すると次のようになります。

SLEEP_SEC = 60
MAX_RETRY = 3

begin
  # Google Sheets API の呼び出し処理(1)
rescue => e
  if retry_count >= MAX_RETRY
    # リトライ回数オーバー
    raise e
  end
  retry_count += 1
  # リトライ待機中
  sleep SLEEP_SEC
  retry
end

# 他の処理(1)

begin
  # Google Sheets API の呼び出し処理(2)
rescue => e
  if retry_count >= MAX_RETRY
    # リトライ回数オーバー
    raise e
  end
  retry_count += 1
  # リトライ待機中
  sleep SLEEP_SEC
  retry
end

# 他の処理(2)

begin
  # Google Sheets API の呼び出し処理(3)
rescue => e
  if retry_count >= MAX_RETRY
    # リトライ回数オーバー
    raise e
  end
  retry_count += 1
  # リトライ待機中
  sleep SLEEP_SEC
  retry
end

# 他の処理(3)

Google Sheets APIではどの処理で回数制限がオーバーするかわからないので、
リトライさせたい処理が多いとコードが煩雑になります。

2. メソッドやクラスに切り出す

class RescueRetryUtil

  def initialize(sleep_sec:, retry_count:)
    @sleep_sec = sleep_sec
    @retry_count = retry_count
  end

  def call(&block)
    retry_count = 0
    begin
      block.call
    rescue => e
      if retry_count >= @retry_count
		    # リトライ回数オーバー
        raise e
      end
      retry_count += 1
		  # リトライ待機中
      sleep @sleep_sec
      retry
    end
  end

end

# 呼び出し例

util = RescueRetryUtil.new(sleep_sec: 60, retry_count: 3)

util.call do
  # Google Sheets API の呼び出し処理(1)
end

# 他の処理(1)

util.call do
  # Google Sheets API の呼び出し処理(2)
end

# 他の処理(2)

util.call do
  # Google Sheets API の呼び出し処理(3)
end

# 他の処理(3)

この例ではクラスにしていますが、状況に応じてコントローラーのメソッドなどに切り出しても良いでしょう。

3. Gemを使う(Retryable)

Retryableなどの公開されているGemを使うという手もあります。

https://github.com/nfedyashev/retryable

最後に

Gemがあるのでそちらを使ってサクッと作るのも良いですが、
すごい高機能なので使いこなすのが大変かもしれません。

自分で再処理のコードを書くと、用途に応じてコードを追記することもできます。
例えば、リトライした場合はログに状況を書き出すとか。
(Retryableでも可能ですがひと手間かかります)

P.S.
リトライ回数は、再処理の回数を表すのか、トライの回数を表すのか、どちらが一般的なのでしょう?

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?