CarrierWaveでリトライを実装する
CarrierWave経由でS3にファイルをアップロードしているとたまにS3から503が返ることがあります。
呼び出し元でリトライ処理を行っても良いのですがリトライの範囲を間違うと大変なのと毎回呼び出し元でリトライを意識させるのも難しいと思いCarrierWave側でリトライするようにできないか試してみました。
ソースコード
fukata/study-carrierwave-retryable
使い方
CarrierWave::Storage::Fog
を継承して必要なメソッドでリトライさせるようにしました。
リトライの条件などはアプリケーションに合わせて変更した方が良いと思います。
class RetryableStorageFog < CarrierWave::Storage::Fog
def store!(file)
retryable(__method__) { super }
end
def cache!(new_file)
retryable(__method__) { super }
end
def retrieve_from_cache!(identifier)
retryable(__method__) { super }
end
def retrieve!(identifier)
retryable(__method__) { super }
end
private
def retryable(method_name)
retryable_options = {
tries: 5,
sleep: lambda{|retries|
retries += 1
sleep_seconds = 2**retries
Rails.logger.warn("[RetryableStorageFog##{method_name}] sleep=#{sleep_seconds}, retries=#{retries}")
sleep_seconds
},
on: [StandardError],
}
Retryable.retryable(retryable_options) do |retries, e|
if retries > 0
Rails.logger.warn("[RetryableStorageFog##{method_name}] retries=#{retries}, e=#{e}")
end
yield
end
end
end
あとはUploaderに指定するだけです。
class ImageUploader < CarrierWave::Uploader::Base
storage RetryableStorageFog
cache_storage RetryableStorageFog
end
更新履歴
- 2b9bf4c 2022-07-31T12:35:39+09:00 add post