はじめに
Railsのプロジェクトに限ったことではないですが外部のAPIを呼び出すはよくあることだと思います.
RubyにはいくつかHTTPクライアントのGemがありRailsのプロジェクトで利用できますが今回はFaradayというGemを用います。
APIが構えてあるサーバやAPIまでのネットワークなど一時的な高負荷などが原因でAPIへのリクエストが失敗したときに同じ内容のリクエストをかけたいケースがあります.
Faradayを用いることでリトライの処理が簡単に記述できるので紹介していきます。
インストール
gem 'faraday'
or
gem install faraday
faraday-retry
Faradayでリトライを実装する場合faradayのとは別にfaraday-retryが必要です.
gem 'faraday-retry'
or
# console
gem install faraday-retry
ver 1.x vs 2.x
faradayの(2023/10/08)最新のバージョンは2.7.11ですが1系であればfaradayをインストールすればfaraday-retryがバンドルされてきますが2系の場合、別途faraday-retryをインストールする必要があるようです.
インストールするfaradayのバージョンによって設定が異なるので注意が必要です.
Gemfile.lock
v1.10.0
# === 略 ====
faraday (1.10.0)
faraday-em_http (~> 1.0)
faraday-em_synchrony (~> 1.0)
faraday-excon (~> 1.1)
faraday-httpclient (~> 1.0)
faraday-multipart (~> 1.0)
faraday-net_http (~> 1.0)
faraday-net_http_persistent (~> 1.0)
faraday-patron (~> 1.0)
faraday-rack (~> 1.0)
faraday-retry (~> 1.0)
ruby2_keywords (>= 0.0.4)
faraday-em_http (1.0.0)
faraday-em_synchrony (1.0.0)
faraday-excon (1.1.0)
faraday-httpclient (1.0.1)
faraday-multipart (1.0.4)
multipart-post (~> 2)
faraday-net_http (1.0.1)
faraday-net_http_persistent (1.2.0)
faraday-patron (1.0.0)
faraday-rack (1.0.0)
faraday-retry (1.0.3)
# === 略 ====
v2.7.11
# === 略 ====
faraday (2.7.11)
base64
faraday-net_http (>= 2.0, < 3.1)
ruby2_keywords (>= 0.0.4)
faraday-net_http (3.0.2)
# === 略 ====
プログラムを書く
実際にプログラムを書いてリトライの挙動を確認してみます.
今回は簡単なAPIを作成して試してみます.
(命名は適当なので気にしないでください)
リクエストする側
indexを呼ぶとfaradayでリクエスト処理が記述されたメソッドを呼びます.
リクエスト結果のステータスが408だった場合にリトライを最大5回するように設定してあります.
Faradayのインスタンスをnewする際にretry用の設定を引数として渡してやればOKです.
特定の例外が発生した場合にリトライされるようにもできます.
class ShowController < ApplicationController
def index
response = api_request
render json: response
end
private
def api_request
retry_options = { # リトライの設定
max: 5,
interval: 0.05,
interval_randomness: 0.5,
backoff_factor: 2,
methods: %i[get post],
retry_statuses: [408]
}
connection = Faraday.new(url: "http://localhost:3001", headers: { 'Content-Type' => 'application/json' } ) do |f|
f.request :retry, retry_options
f.response :logger, Rails.logger
f.adapter Faraday.default_adapter
end
res = connection.post('/server/api') do |req|
req.headers['Content-Type'] = 'application/json'
req.body = { hoge: 100 }.to_json
end
res
end
end
API側
ほぼ何もしないAPIですが408を返して強制的にタイムアウト判定させてfaradayにリトライさせます.
class ServerController < ApplicationController
def api
render json: { hogehoge: 'api' }, status: 408
end
end
実行
上のウィンドウでshow/indexをcurlで呼び出してFaradayにリクエストさせています.
APIは必ず408ステータスを返すのでタイムアウトになりリトライをします.
api_requestにメソッドにループや例外処理がないのにAPI側に5回リクエストされた形跡がありFaradayがリトライしたことが伺えます.
まとめ
Faradayを用いたHTTPリクエストのリトライ処理を紹介しました、Faradayは高機能で他にも色々な機能があります.
Faradayを導入する場合、単なるHTTPのクライアントとしてのみ使うともったいないので数ある機能を深掘りして活用してくようにしたいです。
