はじめに
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のクライアントとしてのみ使うともったいないので数ある機能を深掘りして活用してくようにしたいです。